Source Code Cross Referenced for IntroduceIndirectionRefactoring.java in  » IDE-Eclipse » jdt » org » eclipse » jdt » internal » corext » refactoring » code » 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.code 
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:         *******************************************************************************/package org.eclipse.jdt.internal.corext.refactoring.code;
0011:
0012:        import java.lang.reflect.Modifier;
0013:        import java.util.ArrayList;
0014:        import java.util.Arrays;
0015:        import java.util.HashMap;
0016:        import java.util.Iterator;
0017:        import java.util.List;
0018:        import java.util.Map;
0019:
0020:        import org.eclipse.core.runtime.Assert;
0021:        import org.eclipse.core.runtime.CoreException;
0022:        import org.eclipse.core.runtime.IProgressMonitor;
0023:        import org.eclipse.core.runtime.NullProgressMonitor;
0024:        import org.eclipse.core.runtime.OperationCanceledException;
0025:        import org.eclipse.core.runtime.SubProgressMonitor;
0026:
0027:        import org.eclipse.core.resources.IFile;
0028:
0029:        import org.eclipse.ltk.core.refactoring.Change;
0030:        import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
0031:        import org.eclipse.ltk.core.refactoring.RefactoringStatus;
0032:        import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
0033:
0034:        import org.eclipse.jdt.core.Flags;
0035:        import org.eclipse.jdt.core.IClassFile;
0036:        import org.eclipse.jdt.core.ICompilationUnit;
0037:        import org.eclipse.jdt.core.IJavaElement;
0038:        import org.eclipse.jdt.core.IJavaProject;
0039:        import org.eclipse.jdt.core.IMember;
0040:        import org.eclipse.jdt.core.IMethod;
0041:        import org.eclipse.jdt.core.IPackageFragment;
0042:        import org.eclipse.jdt.core.IType;
0043:        import org.eclipse.jdt.core.ITypeHierarchy;
0044:        import org.eclipse.jdt.core.JavaModelException;
0045:        import org.eclipse.jdt.core.dom.AST;
0046:        import org.eclipse.jdt.core.dom.ASTNode;
0047:        import org.eclipse.jdt.core.dom.ASTParser;
0048:        import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
0049:        import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
0050:        import org.eclipse.jdt.core.dom.Block;
0051:        import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
0052:        import org.eclipse.jdt.core.dom.CompilationUnit;
0053:        import org.eclipse.jdt.core.dom.Expression;
0054:        import org.eclipse.jdt.core.dom.ExpressionStatement;
0055:        import org.eclipse.jdt.core.dom.IBinding;
0056:        import org.eclipse.jdt.core.dom.IMethodBinding;
0057:        import org.eclipse.jdt.core.dom.ITypeBinding;
0058:        import org.eclipse.jdt.core.dom.Javadoc;
0059:        import org.eclipse.jdt.core.dom.MethodDeclaration;
0060:        import org.eclipse.jdt.core.dom.MethodInvocation;
0061:        import org.eclipse.jdt.core.dom.Name;
0062:        import org.eclipse.jdt.core.dom.ParameterizedType;
0063:        import org.eclipse.jdt.core.dom.PrimitiveType;
0064:        import org.eclipse.jdt.core.dom.ReturnStatement;
0065:        import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
0066:        import org.eclipse.jdt.core.dom.Statement;
0067:        import org.eclipse.jdt.core.dom.SuperMethodInvocation;
0068:        import org.eclipse.jdt.core.dom.ThisExpression;
0069:        import org.eclipse.jdt.core.dom.Type;
0070:        import org.eclipse.jdt.core.dom.TypeParameter;
0071:        import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
0072:        import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
0073:        import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
0074:        import org.eclipse.jdt.core.refactoring.descriptors.IntroduceIndirectionDescriptor;
0075:        import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
0076:        import org.eclipse.jdt.core.search.IJavaSearchConstants;
0077:        import org.eclipse.jdt.core.search.IJavaSearchScope;
0078:        import org.eclipse.jdt.core.search.SearchMatch;
0079:        import org.eclipse.jdt.core.search.SearchPattern;
0080:
0081:        import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
0082:        import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
0083:        import org.eclipse.jdt.internal.corext.dom.ASTNodes;
0084:        import org.eclipse.jdt.internal.corext.dom.Bindings;
0085:        import org.eclipse.jdt.internal.corext.dom.NodeFinder;
0086:        import org.eclipse.jdt.internal.corext.refactoring.Checks;
0087:        import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
0088:        import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
0089:        import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
0090:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
0091:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
0092:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory;
0093:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine;
0094:        import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
0095:        import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
0096:        import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange;
0097:        import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
0098:        import org.eclipse.jdt.internal.corext.refactoring.rename.RippleMethodFinder2;
0099:        import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
0100:        import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
0101:        import org.eclipse.jdt.internal.corext.refactoring.structure.MemberVisibilityAdjustor;
0102:        import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
0103:        import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
0104:        import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
0105:        import org.eclipse.jdt.internal.corext.util.JdtFlags;
0106:        import org.eclipse.jdt.internal.corext.util.Messages;
0107:        import org.eclipse.jdt.internal.corext.util.MethodOverrideTester;
0108:
0109:        import org.eclipse.jdt.ui.CodeGeneration;
0110:        import org.eclipse.jdt.ui.JavaElementLabels;
0111:
0112:        import org.eclipse.jdt.internal.ui.JavaPlugin;
0113:
0114:        /**
0115:         * 
0116:         * This refactoring creates a wrapper around a certain method and redirects callers of the original
0117:         * method to the newly created method (called "intermediary method").
0118:         *  
0119:         * If invoked on a method call, the user may select whether to only update the selected call or
0120:         * all other calls as well. If invoked on a method declaration, the user may select whether to 
0121:         * update calls at all. An intermediary method will be created in both cases.
0122:         *  
0123:         * Creating indirections is possible for both source and binary methods. Select an invocation of the method or
0124:         * the declaring method itself, for example in the outline view.
0125:         *  
0126:         * Note that in case of methods inside generic types, the parameters of the declaring type of the selected method
0127:         * will be added to the method definition, rendering it generic as well.
0128:         *  
0129:         * If any of the calls cannot see the intermediary method due to visibility problems with enclosing types
0130:         * of the intermediary method, visibility will be adjusted. If the intermediary method is not able to
0131:         * see the target method, this refactoring will try to adjust the visibility of the target method and
0132:         * enclosing types as well. However, the latter is only possible if the target method is from source.
0133:         * 
0134:         * @since 3.2
0135:         * 
0136:         */
0137:        public class IntroduceIndirectionRefactoring extends
0138:                ScriptableRefactoring {
0139:
0140:            /**
0141:             * The compilation unit in which the user invoked this refactoring (if any)
0142:             */
0143:            private ICompilationUnit fSelectionCompilationUnit;
0144:            /**
0145:             * The class file (with source) in which the user invoked this refactoring (if any)
0146:             */
0147:            private IClassFile fSelectionClassFile;
0148:            /**
0149:             * The start of the user selection inside the selected
0150:             * compilation unit (if any)
0151:             */
0152:            private int fSelectionStart;
0153:            /**
0154:             * The length of the user selection inside the selected
0155:             * compilation unit (if any)
0156:             */
0157:            private int fSelectionLength;
0158:            /**
0159:             * The selected MethodInvocation (if any). This field is used
0160:             * to update this particular invocation in non-reference mode.
0161:             */
0162:            private MethodInvocation fSelectionMethodInvocation;
0163:
0164:            // Intermediary information:
0165:
0166:            /**
0167:             * The class in which to place the intermediary method
0168:             */
0169:            private IType fIntermediaryClass;
0170:            /**
0171:             * The binding of the intermediary class
0172:             */
0173:            private ITypeBinding fIntermediaryClassBinding;
0174:            /**
0175:             * The name of the intermediary method
0176:             */
0177:            private String fIntermediaryMethodName;
0178:            /**
0179:             * The type for the additional parameter for the intermediary. This
0180:             * type is determined from all known references.
0181:             */
0182:            private ITypeBinding fIntermediaryFirstParameterType;
0183:
0184:            // Target information:
0185:
0186:            /**
0187:             * The originally selected target method (i.e., the one to be encapsulated)
0188:             */
0189:            private IMethod fTargetMethod;
0190:            /**
0191:             * The binding of the originally selected target method
0192:             */
0193:            private IMethodBinding fTargetMethodBinding;
0194:
0195:            // Other information:
0196:
0197:            /**
0198:             * If true, all references to the target method are replaced with calls to
0199:             * the intermediary.
0200:             */
0201:            private boolean fUpdateReferences;
0202:            /**
0203:             * CompilationUnitRewrites for all affected cus
0204:             */
0205:            private Map/* <ICompilationUnit,CompilationUnitRewrite> */fRewrites;
0206:            /**
0207:             * Text change manager (actually a CompilationUnitChange manager) which
0208:             * manages all changes.
0209:             */
0210:            private TextChangeManager fTextChangeManager;
0211:
0212:            // Visibility
0213:
0214:            /**
0215:             * The visibility adjustor
0216:             */
0217:            private MemberVisibilityAdjustor fAdjustor;
0218:            /**
0219:             * Visibility adjustments for the intermediary
0220:             */
0221:            private Map/*IMember, IVisibilityAdjustment*/fIntermediaryAdjustments;
0222:
0223:            private class NoOverrideProgressMonitor extends SubProgressMonitor {
0224:
0225:                public NoOverrideProgressMonitor(IProgressMonitor monitor,
0226:                        int ticks) {
0227:                    super (monitor, ticks,
0228:                            SubProgressMonitor.SUPPRESS_SUBTASK_LABEL);
0229:                }
0230:
0231:                public void setTaskName(String name) {
0232:                    // do nothing
0233:                }
0234:            }
0235:
0236:            // ********* CONSTRUCTORS AND CLASS CREATION ************
0237:
0238:            public IntroduceIndirectionRefactoring(ICompilationUnit unit,
0239:                    int offset, int length) {
0240:                fSelectionCompilationUnit = unit;
0241:                initialize(offset, length);
0242:            }
0243:
0244:            public IntroduceIndirectionRefactoring(IClassFile file, int offset,
0245:                    int length) {
0246:                fSelectionClassFile = file;
0247:                initialize(offset, length);
0248:            }
0249:
0250:            public IntroduceIndirectionRefactoring(IMethod method) {
0251:                fTargetMethod = method;
0252:                initialize(0, 0);
0253:            }
0254:
0255:            private void initialize(int offset, int length) {
0256:                fSelectionStart = offset;
0257:                fSelectionLength = length;
0258:                fUpdateReferences = true;
0259:            }
0260:
0261:            // ********* UI INTERACTION AND STARTUP OPTIONS ************
0262:
0263:            public String getName() {
0264:                return RefactoringCoreMessages.IntroduceIndirectionRefactoring_introduce_indirection_name;
0265:            }
0266:
0267:            public IJavaProject getProject() {
0268:                if (fSelectionCompilationUnit != null)
0269:                    return fSelectionCompilationUnit.getJavaProject();
0270:                if (fSelectionClassFile != null)
0271:                    return fSelectionClassFile.getJavaProject();
0272:                if (fTargetMethod != null)
0273:                    return fTargetMethod.getJavaProject();
0274:                return null;
0275:            }
0276:
0277:            public IPackageFragment getInvocationPackage() {
0278:                return fSelectionCompilationUnit != null ? (IPackageFragment) fSelectionCompilationUnit
0279:                        .getAncestor(IJavaElement.PACKAGE_FRAGMENT)
0280:                        : null;
0281:            }
0282:
0283:            public boolean canEnableUpdateReferences() {
0284:                return true;
0285:            }
0286:
0287:            public void setEnableUpdateReferences(boolean updateReferences) {
0288:                fUpdateReferences = updateReferences;
0289:            }
0290:
0291:            public RefactoringStatus setIntermediaryMethodName(
0292:                    String newMethodName) {
0293:                Assert.isNotNull(newMethodName);
0294:                fIntermediaryMethodName = newMethodName;
0295:                IJavaElement context = fIntermediaryClass != null ? fIntermediaryClass
0296:                        : (IMember) fTargetMethod;
0297:                RefactoringStatus stat = Checks.checkMethodName(newMethodName,
0298:                        context);
0299:                stat.merge(checkOverloading());
0300:                return stat;
0301:            }
0302:
0303:            private RefactoringStatus checkOverloading() {
0304:                try {
0305:                    if (fIntermediaryClass != null) {
0306:                        IMethod[] toCheck = fIntermediaryClass.getMethods();
0307:                        for (int i = 0; i < toCheck.length; i++) {
0308:                            IMethod method = toCheck[i];
0309:                            if (method.getElementName().equals(
0310:                                    fIntermediaryMethodName))
0311:                                return RefactoringStatus
0312:                                        .createWarningStatus(Messages
0313:                                                .format(
0314:                                                        RefactoringCoreMessages.IntroduceIndirectionRefactoring_duplicate_method_name_in_declaring_class_error,
0315:                                                        fIntermediaryMethodName));
0316:                        }
0317:                    }
0318:                } catch (JavaModelException e) {
0319:                    return RefactoringStatus
0320:                            .createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_could_not_parse_declaring_class_error);
0321:                }
0322:                return new RefactoringStatus();
0323:            }
0324:
0325:            public String getIntermediaryMethodName() {
0326:                return fIntermediaryMethodName;
0327:            }
0328:
0329:            /**
0330:             * @param fullyQualifiedTypeName
0331:             * @return status for type name. Use {@link #setIntermediaryMethodName(String)} to check for overridden methods.
0332:             */
0333:            public RefactoringStatus setIntermediaryClassName(
0334:                    String fullyQualifiedTypeName) {
0335:                IType target = null;
0336:
0337:                try {
0338:                    if (fullyQualifiedTypeName.length() == 0)
0339:                        return RefactoringStatus
0340:                                .createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_class_not_selected_error);
0341:
0342:                    // find type (now including secondaries)
0343:                    target = getProject().findType(fullyQualifiedTypeName,
0344:                            new NullProgressMonitor());
0345:                    if (target == null || !target.exists())
0346:                        return RefactoringStatus
0347:                                .createErrorStatus(Messages
0348:                                        .format(
0349:                                                RefactoringCoreMessages.IntroduceIndirectionRefactoring_class_does_not_exist_error,
0350:                                                fullyQualifiedTypeName));
0351:                    if (target.isAnnotation())
0352:                        return RefactoringStatus
0353:                                .createErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_cannot_create_in_annotation);
0354:                    if (target.isInterface())
0355:                        return RefactoringStatus
0356:                                .createErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_cannot_create_on_interface);
0357:                } catch (JavaModelException e) {
0358:                    return RefactoringStatus
0359:                            .createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_unable_determine_declaring_type);
0360:                }
0361:
0362:                if (target.isReadOnly())
0363:                    return RefactoringStatus
0364:                            .createErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_cannot_create_in_readonly);
0365:
0366:                if (target.isBinary())
0367:                    return RefactoringStatus
0368:                            .createErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_cannot_create_in_binary);
0369:
0370:                fIntermediaryClass = target;
0371:
0372:                return new RefactoringStatus();
0373:            }
0374:
0375:            /**
0376:             * Returns the class name of the intermediary class, or the empty string if none has been set yet.
0377:             * @return the intermediary class name or the empty string
0378:             */
0379:            public String getIntermediaryClassName() {
0380:                return fIntermediaryClass != null ? JavaModelUtil
0381:                        .getFullyQualifiedName(fIntermediaryClass) : ""; //$NON-NLS-1$
0382:            }
0383:
0384:            // ********** CONDITION CHECKING **********
0385:
0386:            public RefactoringStatus checkInitialConditions(IProgressMonitor pm)
0387:                    throws CoreException, OperationCanceledException {
0388:                try {
0389:                    pm
0390:                            .beginTask(
0391:                                    RefactoringCoreMessages.IntroduceIndirectionRefactoring_checking_activation,
0392:                                    1);
0393:                    fRewrites = new HashMap();
0394:
0395:                    // This refactoring has been invoked on 
0396:                    // (1) a TextSelection inside an ICompilationUnit or inside an IClassFile (definitely with source), or 
0397:                    // (2) an IMethod inside a ICompilationUnit or inside an IClassFile (with or without source)
0398:
0399:                    if (fTargetMethod == null) {
0400:                        // (1) invoked on a text selection
0401:
0402:                        if (fSelectionStart == 0)
0403:                            return RefactoringStatus
0404:                                    .createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_not_available_on_this _selection);
0405:
0406:                        // if a text selection exists, source is available.
0407:                        CompilationUnit selectionCURoot;
0408:                        ASTNode selectionNode;
0409:                        if (fSelectionCompilationUnit != null) {
0410:                            // compilation unit - could use CuRewrite later on
0411:                            selectionCURoot = getCachedCURewrite(
0412:                                    fSelectionCompilationUnit).getRoot();
0413:                            selectionNode = getSelectedNode(
0414:                                    fSelectionCompilationUnit, selectionCURoot,
0415:                                    fSelectionStart, fSelectionLength);
0416:                        } else {
0417:                            // binary class file - no cu rewrite
0418:                            ASTParser parser = ASTParser.newParser(AST.JLS3);
0419:                            parser.setResolveBindings(true);
0420:                            parser.setSource(fSelectionClassFile);
0421:                            selectionCURoot = (CompilationUnit) parser
0422:                                    .createAST(null);
0423:                            selectionNode = getSelectedNode(null,
0424:                                    selectionCURoot, fSelectionStart,
0425:                                    fSelectionLength);
0426:                        }
0427:
0428:                        if (selectionNode == null)
0429:                            return RefactoringStatus
0430:                                    .createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_not_available_on_this _selection);
0431:
0432:                        IMethodBinding targetMethodBinding = null;
0433:
0434:                        if (selectionNode.getNodeType() == ASTNode.METHOD_INVOCATION) {
0435:                            targetMethodBinding = ((MethodInvocation) selectionNode)
0436:                                    .resolveMethodBinding();
0437:                        } else if (selectionNode.getNodeType() == ASTNode.METHOD_DECLARATION) {
0438:                            targetMethodBinding = ((MethodDeclaration) selectionNode)
0439:                                    .resolveBinding();
0440:                        } else if (selectionNode.getNodeType() == ASTNode.SUPER_METHOD_INVOCATION) {
0441:                            // Allow invocation on super methods calls. makes sense as other
0442:                            // calls or even only the declaration can be updated.
0443:                            targetMethodBinding = ((SuperMethodInvocation) selectionNode)
0444:                                    .resolveMethodBinding();
0445:                        } else {
0446:                            return RefactoringStatus
0447:                                    .createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_not_available_on_this _selection);
0448:                        }
0449:                        fTargetMethodBinding = targetMethodBinding
0450:                                .getMethodDeclaration(); // resolve generics
0451:                        fTargetMethod = (IMethod) fTargetMethodBinding
0452:                                .getJavaElement();
0453:
0454:                        //allow single updating mode if an invocation was selected and the invocation can be updated
0455:                        if (selectionNode instanceof  MethodInvocation
0456:                                && fSelectionCompilationUnit != null)
0457:                            fSelectionMethodInvocation = (MethodInvocation) selectionNode;
0458:
0459:                    } else {
0460:                        // (2) invoked on an IMethod: Source may not be available
0461:
0462:                        if (fTargetMethod.getDeclaringType().isAnnotation())
0463:                            return RefactoringStatus
0464:                                    .createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_not_available_on_annotation);
0465:
0466:                        if (fTargetMethod.getCompilationUnit() != null) {
0467:                            // source method
0468:                            CompilationUnit selectionCURoot = getCachedCURewrite(
0469:                                    fTargetMethod.getCompilationUnit())
0470:                                    .getRoot();
0471:                            MethodDeclaration declaration = ASTNodeSearchUtil
0472:                                    .getMethodDeclarationNode(fTargetMethod,
0473:                                            selectionCURoot);
0474:                            fTargetMethodBinding = declaration.resolveBinding()
0475:                                    .getMethodDeclaration();
0476:                        } else {
0477:                            // binary method - no CURewrite available (and none needed as we cannot update the method anyway)
0478:                            ASTParser parser = ASTParser.newParser(AST.JLS3);
0479:                            parser.setProject(fTargetMethod.getJavaProject());
0480:                            IBinding[] bindings = parser.createBindings(
0481:                                    new IJavaElement[] { fTargetMethod }, null);
0482:                            fTargetMethodBinding = ((IMethodBinding) bindings[0])
0483:                                    .getMethodDeclaration();
0484:                        }
0485:                    }
0486:
0487:                    if (fTargetMethod == null
0488:                            || fTargetMethodBinding == null
0489:                            || (!RefactoringAvailabilityTester
0490:                                    .isIntroduceIndirectionAvailable(fTargetMethod)))
0491:                        return RefactoringStatus
0492:                                .createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_not_available_on_this _selection);
0493:
0494:                    if (fTargetMethod.getDeclaringType().isLocal()
0495:                            || fTargetMethod.getDeclaringType().isAnonymous())
0496:                        return RefactoringStatus
0497:                                .createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_not_available_for_local_or_anonymous_types);
0498:
0499:                    if (fTargetMethod.isConstructor())
0500:                        return RefactoringStatus
0501:                                .createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_not_available_for_constructors);
0502:
0503:                    if (fIntermediaryMethodName == null)
0504:                        fIntermediaryMethodName = fTargetMethod
0505:                                .getElementName();
0506:
0507:                    if (fIntermediaryClass == null) {
0508:                        if (fSelectionCompilationUnit != null
0509:                                && !fSelectionCompilationUnit.isReadOnly())
0510:                            fIntermediaryClass = getEnclosingInitialSelectionMember()
0511:                                    .getDeclaringType();
0512:                        else if (!fTargetMethod.isBinary()
0513:                                && !fTargetMethod.isReadOnly())
0514:                            fIntermediaryClass = fTargetMethod
0515:                                    .getDeclaringType();
0516:                    }
0517:
0518:                    return new RefactoringStatus();
0519:                } finally {
0520:                    pm.done();
0521:                }
0522:            }
0523:
0524:            public RefactoringStatus checkFinalConditions(IProgressMonitor pm)
0525:                    throws CoreException, OperationCanceledException {
0526:
0527:                RefactoringStatus result = new RefactoringStatus();
0528:                fTextChangeManager = new TextChangeManager();
0529:                fIntermediaryFirstParameterType = null;
0530:                fIntermediaryClassBinding = null;
0531:                for (Iterator iter = fRewrites.values().iterator(); iter
0532:                        .hasNext();)
0533:                    ((CompilationUnitRewrite) iter.next())
0534:                            .clearASTAndImportRewrites();
0535:
0536:                int startupTicks = 5;
0537:                int hierarchyTicks = 5;
0538:                int visibilityTicks = 5;
0539:                int referenceTicks = fUpdateReferences ? 30 : 5;
0540:                int creationTicks = 5;
0541:
0542:                pm
0543:                        .beginTask(
0544:                                "", startupTicks + hierarchyTicks + visibilityTicks + referenceTicks + creationTicks); //$NON-NLS-1$
0545:                pm
0546:                        .setTaskName(RefactoringCoreMessages.IntroduceIndirectionRefactoring_checking_conditions);
0547:
0548:                result.merge(Checks.checkMethodName(fIntermediaryMethodName,
0549:                        fIntermediaryClass));
0550:                if (result.hasFatalError())
0551:                    return result;
0552:
0553:                if (fIntermediaryClass == null)
0554:                    return RefactoringStatus
0555:                            .createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_cannot_run_without_intermediary_type);
0556:
0557:                // intermediary class is already non binary/non-enum/non-interface.
0558:                CompilationUnitRewrite imRewrite = getCachedCURewrite(fIntermediaryClass
0559:                        .getCompilationUnit());
0560:                fIntermediaryClassBinding = typeToBinding(fIntermediaryClass,
0561:                        imRewrite.getRoot());
0562:
0563:                fAdjustor = new MemberVisibilityAdjustor(fIntermediaryClass,
0564:                        fIntermediaryClass);
0565:                fIntermediaryAdjustments = new HashMap();
0566:
0567:                // check static method in non-static nested type
0568:                if (fIntermediaryClassBinding.isNested()
0569:                        && !Modifier.isStatic(fIntermediaryClassBinding
0570:                                .getModifiers()))
0571:                    return RefactoringStatus
0572:                            .createFatalErrorStatus(
0573:                                    RefactoringCoreMessages.IntroduceIndirectionRefactoring_cannot_create_in_nested_nonstatic,
0574:                                    JavaStatusContext
0575:                                            .create(fIntermediaryClass));
0576:
0577:                pm.worked(startupTicks);
0578:                if (pm.isCanceled())
0579:                    throw new OperationCanceledException();
0580:
0581:                if (fUpdateReferences) {
0582:                    pm
0583:                            .setTaskName(RefactoringCoreMessages.IntroduceIndirectionRefactoring_checking_conditions
0584:                                    + " " + RefactoringCoreMessages.IntroduceIndirectionRefactoring_looking_for_references); //$NON-NLS-1$
0585:                    result
0586:                            .merge(updateReferences(new NoOverrideProgressMonitor(
0587:                                    pm, referenceTicks)));
0588:                    pm
0589:                            .setTaskName(RefactoringCoreMessages.IntroduceIndirectionRefactoring_checking_conditions);
0590:                } else {
0591:                    // only update the declaration and/or a selected method invocation
0592:                    if (fSelectionMethodInvocation != null) {
0593:                        fIntermediaryFirstParameterType = getExpressionType(fSelectionMethodInvocation);
0594:                        final IMember enclosing = getEnclosingInitialSelectionMember();
0595:                        // create an edit for this particular call
0596:                        result.merge(updateMethodInvocation(
0597:                                fSelectionMethodInvocation, enclosing,
0598:                                getCachedCURewrite(fSelectionCompilationUnit)));
0599:
0600:                        if (!isRewriteKept(fSelectionCompilationUnit))
0601:                            createChangeAndDiscardRewrite(fSelectionCompilationUnit);
0602:
0603:                        // does call see the intermediary method?
0604:                        // => increase visibility of the type of the intermediary method.
0605:                        result.merge(adjustVisibility(fIntermediaryClass,
0606:                                enclosing.getDeclaringType(),
0607:                                new NoOverrideProgressMonitor(pm, 0)));
0608:                    }
0609:                    pm.worked(referenceTicks);
0610:                }
0611:
0612:                if (pm.isCanceled())
0613:                    throw new OperationCanceledException();
0614:
0615:                if (fIntermediaryFirstParameterType == null)
0616:                    fIntermediaryFirstParameterType = fTargetMethodBinding
0617:                            .getDeclaringClass();
0618:
0619:                // The target type and method may have changed - update them
0620:
0621:                IType actualTargetType = (IType) fIntermediaryFirstParameterType
0622:                        .getJavaElement();
0623:                if (!fTargetMethod.getDeclaringType().equals(actualTargetType)) {
0624:                    IMethod actualTargetMethod = new MethodOverrideTester(
0625:                            actualTargetType, actualTargetType
0626:                                    .newSupertypeHierarchy(null))
0627:                            .findOverriddenMethodInHierarchy(actualTargetType,
0628:                                    fTargetMethod);
0629:                    fTargetMethod = actualTargetMethod;
0630:                    fTargetMethodBinding = findMethodBindingInHierarchy(
0631:                            fIntermediaryFirstParameterType, actualTargetMethod);
0632:                    Assert.isNotNull(fTargetMethodBinding);
0633:                }
0634:
0635:                result.merge(checkCanCreateIntermediaryMethod());
0636:                createIntermediaryMethod();
0637:                pm.worked(creationTicks);
0638:
0639:                pm
0640:                        .setTaskName(RefactoringCoreMessages.IntroduceIndirectionRefactoring_checking_conditions
0641:                                + " " + RefactoringCoreMessages.IntroduceIndirectionRefactoring_adjusting_visibility); //$NON-NLS-1$
0642:                result
0643:                        .merge(updateTargetVisibility(new NoOverrideProgressMonitor(
0644:                                pm, 0)));
0645:                result
0646:                        .merge(updateIntermediaryVisibility(new NoOverrideProgressMonitor(
0647:                                pm, 0)));
0648:                pm.worked(visibilityTicks);
0649:                pm
0650:                        .setTaskName(RefactoringCoreMessages.IntroduceIndirectionRefactoring_checking_conditions);
0651:
0652:                createChangeAndDiscardRewrite(fIntermediaryClass
0653:                        .getCompilationUnit());
0654:
0655:                result.merge(Checks.validateModifiesFiles(
0656:                        getAllFilesToModify(), getValidationContext()));
0657:                pm.done();
0658:
0659:                return result;
0660:            }
0661:
0662:            private RefactoringStatus updateTargetVisibility(
0663:                    IProgressMonitor monitor) throws JavaModelException,
0664:                    CoreException {
0665:
0666:                RefactoringStatus result = new RefactoringStatus();
0667:
0668:                // Adjust the visibility of the method and of the referenced type. Note that
0669:                // the target method may not be in the target type; and in this case, the type
0670:                // of the target method does not need a visibility adjustment.
0671:
0672:                // This method is called after all other changes have been 
0673:                // created. Changes induced by this method will be attached to those changes.
0674:
0675:                result
0676:                        .merge(adjustVisibility(
0677:                                (IType) fIntermediaryFirstParameterType
0678:                                        .getJavaElement(), fIntermediaryClass,
0679:                                monitor));
0680:                if (result.hasError())
0681:                    return result; // binary
0682:
0683:                ModifierKeyword neededVisibility = getNeededVisibility(
0684:                        fTargetMethod, fIntermediaryClass);
0685:                if (neededVisibility != null) {
0686:
0687:                    result.merge(adjustVisibility(fTargetMethod,
0688:                            neededVisibility, monitor));
0689:                    if (result.hasError())
0690:                        return result; // binary
0691:
0692:                    // Need to adjust the overridden methods of the target method.
0693:                    ITypeHierarchy hierarchy = fTargetMethod.getDeclaringType()
0694:                            .newTypeHierarchy(null);
0695:                    MethodOverrideTester tester = new MethodOverrideTester(
0696:                            fTargetMethod.getDeclaringType(), hierarchy);
0697:                    IType[] subtypes = hierarchy.getAllSubtypes(fTargetMethod
0698:                            .getDeclaringType());
0699:                    for (int i = 0; i < subtypes.length; i++) {
0700:                        IMethod method = tester.findOverridingMethodInType(
0701:                                subtypes[i], fTargetMethod);
0702:                        if (method != null && method.exists()) {
0703:                            result.merge(adjustVisibility(method,
0704:                                    neededVisibility, monitor));
0705:                            if (monitor.isCanceled())
0706:                                throw new OperationCanceledException();
0707:
0708:                            if (result.hasError())
0709:                                return result; // binary
0710:                        }
0711:                    }
0712:                }
0713:
0714:                return result;
0715:            }
0716:
0717:            private RefactoringStatus updateIntermediaryVisibility(
0718:                    NoOverrideProgressMonitor monitor)
0719:                    throws JavaModelException {
0720:                return rewriteVisibility(fIntermediaryAdjustments, fRewrites,
0721:                        monitor);
0722:            }
0723:
0724:            private RefactoringStatus updateReferences(IProgressMonitor monitor)
0725:                    throws CoreException {
0726:
0727:                RefactoringStatus result = new RefactoringStatus();
0728:
0729:                monitor.beginTask("", 90); //$NON-NLS-1$
0730:
0731:                if (monitor.isCanceled())
0732:                    throw new OperationCanceledException();
0733:
0734:                IMethod[] ripple = RippleMethodFinder2.getRelatedMethods(
0735:                        fTargetMethod, false, new NoOverrideProgressMonitor(
0736:                                monitor, 10), null);
0737:
0738:                if (monitor.isCanceled())
0739:                    throw new OperationCanceledException();
0740:
0741:                SearchResultGroup[] references = Checks
0742:                        .excludeCompilationUnits(getReferences(ripple,
0743:                                new NoOverrideProgressMonitor(monitor, 10),
0744:                                result), result);
0745:
0746:                if (result.hasFatalError())
0747:                    return result;
0748:
0749:                result.merge(Checks
0750:                        .checkCompileErrorsInAffectedFiles(references));
0751:
0752:                if (monitor.isCanceled())
0753:                    throw new OperationCanceledException();
0754:
0755:                int ticksPerCU = references.length == 0 ? 0
0756:                        : 70 / references.length;
0757:
0758:                for (int i = 0; i < references.length; i++) {
0759:                    SearchResultGroup group = references[i];
0760:                    SearchMatch[] searchResults = group.getSearchResults();
0761:                    CompilationUnitRewrite currentCURewrite = getCachedCURewrite(group
0762:                            .getCompilationUnit());
0763:
0764:                    for (int j = 0; j < searchResults.length; j++) {
0765:
0766:                        SearchMatch match = searchResults[j];
0767:                        if (match.isInsideDocComment())
0768:                            continue;
0769:
0770:                        IMember enclosingMember = (IMember) match.getElement();
0771:                        ASTNode target = getSelectedNode(group
0772:                                .getCompilationUnit(), currentCURewrite
0773:                                .getRoot(), match.getOffset(), match
0774:                                .getLength());
0775:
0776:                        if (target instanceof  SuperMethodInvocation) {
0777:                            // Cannot retarget calls to super - add a warning
0778:                            result
0779:                                    .merge(createWarningAboutCall(
0780:                                            enclosingMember,
0781:                                            target,
0782:                                            RefactoringCoreMessages.IntroduceIndirectionRefactoring_call_warning_super _keyword));
0783:                            continue;
0784:                        }
0785:
0786:                        Assert
0787:                                .isTrue(target instanceof  MethodInvocation,
0788:                                        "Element of call should be a MethodInvocation."); //$NON-NLS-1$
0789:
0790:                        MethodInvocation invocation = (MethodInvocation) target;
0791:                        ITypeBinding typeBinding = getExpressionType(invocation);
0792:
0793:                        if (fIntermediaryFirstParameterType == null) {
0794:                            // no highest type yet
0795:                            fIntermediaryFirstParameterType = typeBinding
0796:                                    .getTypeDeclaration();
0797:                        } else {
0798:                            // check if current type is higher
0799:                            result.merge(findCommonParent(typeBinding
0800:                                    .getTypeDeclaration()));
0801:                        }
0802:
0803:                        if (result.hasFatalError())
0804:                            return result;
0805:
0806:                        // create an edit for this particular call
0807:                        result.merge(updateMethodInvocation(invocation,
0808:                                enclosingMember, currentCURewrite));
0809:
0810:                        // does call see the intermediary method?
0811:                        // => increase visibility of the type of the intermediary method.
0812:                        result.merge(adjustVisibility(fIntermediaryClass,
0813:                                enclosingMember.getDeclaringType(),
0814:                                new NoOverrideProgressMonitor(monitor, 0)));
0815:
0816:                        if (monitor.isCanceled())
0817:                            throw new OperationCanceledException();
0818:                    }
0819:
0820:                    if (!isRewriteKept(group.getCompilationUnit()))
0821:                        createChangeAndDiscardRewrite(group
0822:                                .getCompilationUnit());
0823:
0824:                    monitor.worked(ticksPerCU);
0825:                }
0826:
0827:                monitor.done();
0828:                return result;
0829:            }
0830:
0831:            private RefactoringStatus findCommonParent(ITypeBinding typeBinding)
0832:                    throws JavaModelException {
0833:
0834:                RefactoringStatus status = new RefactoringStatus();
0835:
0836:                ITypeBinding highest = fIntermediaryFirstParameterType;
0837:                ITypeBinding current = typeBinding;
0838:
0839:                if (current.equals(highest)
0840:                        || Bindings.isSuperType(highest, current))
0841:                    // current is the same as highest or highest is already a supertype of current in the same hierarchy => no change
0842:                    return status;
0843:
0844:                // find lowest common supertype with the method
0845:                // search in bottom-up order 
0846:                ITypeBinding[] currentAndSupers = getTypeAndAllSuperTypes(current);
0847:                ITypeBinding[] highestAndSupers = getTypeAndAllSuperTypes(highest);
0848:
0849:                ITypeBinding foundBinding = null;
0850:                for (int i1 = 0; i1 < currentAndSupers.length; i1++) {
0851:                    for (int i2 = 0; i2 < highestAndSupers.length; i2++) {
0852:                        if (highestAndSupers[i2]
0853:                                .isEqualTo(currentAndSupers[i1])
0854:                                && (Bindings.findMethodInHierarchy(
0855:                                        highestAndSupers[i2],
0856:                                        fTargetMethodBinding.getName(),
0857:                                        fTargetMethodBinding
0858:                                                .getParameterTypes()) != null)) {
0859:                            foundBinding = highestAndSupers[i2];
0860:                            break;
0861:                        }
0862:                    }
0863:                    if (foundBinding != null)
0864:                        break;
0865:                }
0866:
0867:                if (foundBinding != null) {
0868:                    fIntermediaryFirstParameterType = foundBinding;
0869:                } else {
0870:                    String type1 = fIntermediaryFirstParameterType
0871:                            .getQualifiedName();
0872:                    String type2 = current.getQualifiedName();
0873:                    status
0874:                            .addFatalError(Messages
0875:                                    .format(
0876:                                            RefactoringCoreMessages.IntroduceIndirectionRefactoring_open_hierarchy_error,
0877:                                            new String[] { type1, type2 }));
0878:                }
0879:
0880:                return status;
0881:            }
0882:
0883:            // ******************** CHANGE CREATION ***********************
0884:
0885:            public Change createChange(IProgressMonitor pm)
0886:                    throws CoreException, OperationCanceledException {
0887:                final Map arguments = new HashMap();
0888:                String project = null;
0889:                IJavaProject javaProject = fTargetMethod.getJavaProject();
0890:                if (javaProject != null)
0891:                    project = javaProject.getElementName();
0892:                int flags = JavaRefactoringDescriptor.JAR_MIGRATION
0893:                        | JavaRefactoringDescriptor.JAR_REFACTORING
0894:                        | RefactoringDescriptor.STRUCTURAL_CHANGE
0895:                        | RefactoringDescriptor.MULTI_CHANGE;
0896:                final IType declaring = fTargetMethod.getDeclaringType();
0897:                try {
0898:                    if (declaring.isLocal() || declaring.isAnonymous())
0899:                        flags |= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
0900:                } catch (JavaModelException exception) {
0901:                    JavaPlugin.log(exception);
0902:                }
0903:                final String description = Messages
0904:                        .format(
0905:                                RefactoringCoreMessages.IntroduceIndirectionRefactoring_descriptor_description_short,
0906:                                fTargetMethod.getElementName());
0907:                final String header = Messages
0908:                        .format(
0909:                                RefactoringCoreMessages.IntroduceIndirectionRefactoring_descriptor_description,
0910:                                new String[] {
0911:                                        JavaElementLabels
0912:                                                .getTextLabel(
0913:                                                        fTargetMethod,
0914:                                                        JavaElementLabels.ALL_FULLY_QUALIFIED),
0915:                                        JavaElementLabels
0916:                                                .getTextLabel(
0917:                                                        declaring,
0918:                                                        JavaElementLabels.ALL_FULLY_QUALIFIED) });
0919:                final JDTRefactoringDescriptorComment comment = new JDTRefactoringDescriptorComment(
0920:                        project, this , header);
0921:                comment
0922:                        .addSetting(Messages
0923:                                .format(
0924:                                        RefactoringCoreMessages.IntroduceIndirectionRefactoring_original_pattern,
0925:                                        JavaElementLabels
0926:                                                .getTextLabel(
0927:                                                        fTargetMethod,
0928:                                                        JavaElementLabels.ALL_FULLY_QUALIFIED)));
0929:                comment
0930:                        .addSetting(Messages
0931:                                .format(
0932:                                        RefactoringCoreMessages.IntroduceIndirectionRefactoring_method_pattern,
0933:                                        fIntermediaryMethodName));
0934:                comment
0935:                        .addSetting(Messages
0936:                                .format(
0937:                                        RefactoringCoreMessages.IntroduceIndirectionRefactoring_declaring_pattern,
0938:                                        JavaElementLabels
0939:                                                .getTextLabel(
0940:                                                        fIntermediaryClass,
0941:                                                        JavaElementLabels.ALL_FULLY_QUALIFIED)));
0942:                if (fUpdateReferences)
0943:                    comment
0944:                            .addSetting(RefactoringCoreMessages.JavaRefactoringDescriptor_update_references);
0945:                final IntroduceIndirectionDescriptor descriptor = new IntroduceIndirectionDescriptor(
0946:                        project, description, comment.asString(), arguments,
0947:                        flags);
0948:                arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT,
0949:                        JavaRefactoringDescriptorUtil.elementToHandle(project,
0950:                                fTargetMethod));
0951:                arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME,
0952:                        fIntermediaryMethodName);
0953:                arguments.put(
0954:                        JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + 1,
0955:                        JavaRefactoringDescriptorUtil.elementToHandle(project,
0956:                                fIntermediaryClass));
0957:                arguments.put(
0958:                        JavaRefactoringDescriptorUtil.ATTRIBUTE_REFERENCES,
0959:                        Boolean.valueOf(fUpdateReferences).toString());
0960:                return new DynamicValidationRefactoringChange(
0961:                        descriptor,
0962:                        RefactoringCoreMessages.IntroduceIndirectionRefactoring_introduce_indirection,
0963:                        fTextChangeManager.getAllChanges());
0964:            }
0965:
0966:            // ******************* CREATE INTERMEDIARY **********************
0967:
0968:            /**
0969:             * Checks whether the target method can be created. Note that this
0970:             * can only be done after fDelegateParameterType has been initialized.
0971:             * @return resulting status
0972:             * @throws JavaModelException 
0973:             */
0974:            private RefactoringStatus checkCanCreateIntermediaryMethod()
0975:                    throws JavaModelException {
0976:                // check if method already exists:
0977:                List parameterBindings = new ArrayList();
0978:                if (!isStaticTarget())
0979:                    parameterBindings.add(fIntermediaryFirstParameterType);
0980:                parameterBindings.addAll(Arrays.asList(fTargetMethodBinding
0981:                        .getParameterTypes()));
0982:                return Checks.checkMethodInType(fIntermediaryClassBinding,
0983:                        fIntermediaryMethodName,
0984:                        (ITypeBinding[]) parameterBindings
0985:                                .toArray(new ITypeBinding[parameterBindings
0986:                                        .size()]));
0987:            }
0988:
0989:            private void createIntermediaryMethod() throws CoreException {
0990:
0991:                CompilationUnitRewrite imRewrite = getCachedCURewrite(fIntermediaryClass
0992:                        .getCompilationUnit());
0993:                AST ast = imRewrite.getAST();
0994:                MethodDeclaration intermediary = ast.newMethodDeclaration();
0995:
0996:                // Name
0997:                intermediary
0998:                        .setName(ast.newSimpleName(fIntermediaryMethodName));
0999:
1000:                // Flags
1001:                List modifiers = intermediary.modifiers();
1002:                modifiers.add(imRewrite.getAST().newModifier(
1003:                        ModifierKeyword.PUBLIC_KEYWORD));
1004:                modifiers.add(imRewrite.getAST().newModifier(
1005:                        ModifierKeyword.STATIC_KEYWORD));
1006:
1007:                // Parameters
1008:                String targetParameterName = StubUtility.suggestArgumentName(
1009:                        getProject(),
1010:                        fIntermediaryFirstParameterType.getName(),
1011:                        fTargetMethod.getParameterNames());
1012:
1013:                if (!isStaticTarget()) {
1014:                    // Add first param
1015:                    SingleVariableDeclaration parameter = imRewrite.getAST()
1016:                            .newSingleVariableDeclaration();
1017:                    Type t = imRewrite.getImportRewrite()
1018:                            .addImport(fIntermediaryFirstParameterType,
1019:                                    imRewrite.getAST());
1020:                    if (fIntermediaryFirstParameterType.isGenericType()) {
1021:                        ParameterizedType parameterized = imRewrite.getAST()
1022:                                .newParameterizedType(t);
1023:                        ITypeBinding[] typeParameters = fIntermediaryFirstParameterType
1024:                                .getTypeParameters();
1025:                        for (int i = 0; i < typeParameters.length; i++)
1026:                            parameterized.typeArguments().add(
1027:                                    imRewrite.getImportRewrite().addImport(
1028:                                            typeParameters[i],
1029:                                            imRewrite.getAST()));
1030:                        t = parameterized;
1031:                    }
1032:                    parameter.setType(t);
1033:                    parameter.setName(imRewrite.getAST().newSimpleName(
1034:                            targetParameterName));
1035:                    intermediary.parameters().add(parameter);
1036:                }
1037:                // Add other params
1038:                copyArguments(intermediary, imRewrite);
1039:
1040:                // Add type parameters of declaring class (and enclosing classes)
1041:                if (!isStaticTarget()
1042:                        && fIntermediaryFirstParameterType.isGenericType())
1043:                    addTypeParameters(imRewrite, intermediary.typeParameters(),
1044:                            fIntermediaryFirstParameterType);
1045:
1046:                // Add type params of method
1047:                copyTypeParameters(intermediary, imRewrite);
1048:
1049:                // Return type
1050:                intermediary.setReturnType2(imRewrite.getImportRewrite()
1051:                        .addImport(fTargetMethodBinding.getReturnType(), ast));
1052:
1053:                // Exceptions
1054:                copyExceptions(intermediary, imRewrite);
1055:
1056:                // Body
1057:                MethodInvocation invocation = imRewrite.getAST()
1058:                        .newMethodInvocation();
1059:                invocation.setName(imRewrite.getAST().newSimpleName(
1060:                        fTargetMethod.getElementName()));
1061:                if (isStaticTarget()) {
1062:                    Type type = imRewrite.getImportRewrite().addImport(
1063:                            fTargetMethodBinding.getDeclaringClass(), ast);
1064:                    invocation.setExpression(ASTNodeFactory.newName(ast,
1065:                            ASTNodes.asString(type)));
1066:                } else {
1067:                    invocation.setExpression(imRewrite.getAST().newSimpleName(
1068:                            targetParameterName));
1069:                }
1070:                copyInvocationParameters(invocation, ast);
1071:                Statement call = encapsulateInvocation(intermediary, invocation);
1072:
1073:                final Block body = imRewrite.getAST().newBlock();
1074:                body.statements().add(call);
1075:                intermediary.setBody(body);
1076:
1077:                // method comment
1078:                ICompilationUnit targetCU = imRewrite.getCu();
1079:                if (StubUtility.doAddComments(targetCU.getJavaProject())) {
1080:                    String comment = CodeGeneration.getMethodComment(targetCU,
1081:                            getIntermediaryClassName(), intermediary, null,
1082:                            StubUtility.getLineDelimiterUsed(targetCU));
1083:                    if (comment != null) {
1084:                        Javadoc javadoc = (Javadoc) imRewrite.getASTRewrite()
1085:                                .createStringPlaceholder(comment,
1086:                                        ASTNode.JAVADOC);
1087:                        intermediary.setJavadoc(javadoc);
1088:                    }
1089:                }
1090:
1091:                // Add the completed method to the intermediary type:
1092:
1093:                // Intermediary class is non-anonymous
1094:                AbstractTypeDeclaration type = (AbstractTypeDeclaration) typeToDeclaration(
1095:                        fIntermediaryClass, imRewrite.getRoot());
1096:                ChildListPropertyDescriptor typeBodyDeclarationsProperty = typeToBodyDeclarationProperty(
1097:                        fIntermediaryClass, imRewrite.getRoot());
1098:
1099:                ListRewrite bodyDeclarationsListRewrite = imRewrite
1100:                        .getASTRewrite().getListRewrite(type,
1101:                                typeBodyDeclarationsProperty);
1102:                bodyDeclarationsListRewrite
1103:                        .insertAt(
1104:                                intermediary,
1105:                                ASTNodes.getInsertionIndex(intermediary, type
1106:                                        .bodyDeclarations()),
1107:                                imRewrite
1108:                                        .createGroupDescription(RefactoringCoreMessages.IntroduceIndirectionRefactoring_group_description_create_new_method));
1109:            }
1110:
1111:            private void addTypeParameters(CompilationUnitRewrite imRewrite,
1112:                    List newTypeParameters, ITypeBinding parent) {
1113:
1114:                ITypeBinding enclosing = parent.getDeclaringClass();
1115:                if (enclosing != null)
1116:                    addTypeParameters(imRewrite, newTypeParameters, enclosing);
1117:
1118:                ITypeBinding[] typeParameters = parent.getTypeParameters();
1119:                for (int i = 0; i < typeParameters.length; i++) {
1120:                    TypeParameter ntp = imRewrite.getAST().newTypeParameter();
1121:                    ntp.setName(imRewrite.getAST().newSimpleName(
1122:                            typeParameters[i].getName()));
1123:                    ITypeBinding[] bounds = typeParameters[i].getTypeBounds();
1124:                    for (int j = 0; j < bounds.length; j++)
1125:                        if (!"java.lang.Object".equals(bounds[j].getQualifiedName())) //$NON-NLS-1$
1126:                            ntp.typeBounds().add(
1127:                                    imRewrite.getImportRewrite().addImport(
1128:                                            bounds[j], imRewrite.getAST()));
1129:                    newTypeParameters.add(ntp);
1130:                }
1131:            }
1132:
1133:            private Statement encapsulateInvocation(
1134:                    MethodDeclaration declaration, MethodInvocation invocation) {
1135:                final Type type = declaration.getReturnType2();
1136:
1137:                if (type == null
1138:                        || (type instanceof  PrimitiveType && PrimitiveType.VOID
1139:                                .equals(((PrimitiveType) type)
1140:                                        .getPrimitiveTypeCode())))
1141:                    return invocation.getAST().newExpressionStatement(
1142:                            invocation);
1143:
1144:                ReturnStatement statement = invocation.getAST()
1145:                        .newReturnStatement();
1146:                statement.setExpression(invocation);
1147:                return statement;
1148:            }
1149:
1150:            private void copyInvocationParameters(MethodInvocation invocation,
1151:                    AST ast) throws JavaModelException {
1152:                String[] names = fTargetMethod.getParameterNames();
1153:                for (int i = 0; i < names.length; i++)
1154:                    invocation.arguments().add(ast.newSimpleName(names[i]));
1155:            }
1156:
1157:            private void copyArguments(MethodDeclaration intermediary,
1158:                    CompilationUnitRewrite rew) throws JavaModelException {
1159:                String[] names = fTargetMethod.getParameterNames();
1160:                ITypeBinding[] types = fTargetMethodBinding.getParameterTypes();
1161:                for (int i = 0; i < names.length; i++) {
1162:                    ITypeBinding typeBinding = types[i];
1163:                    SingleVariableDeclaration newElement = rew.getAST()
1164:                            .newSingleVariableDeclaration();
1165:                    newElement.setName(rew.getAST().newSimpleName(names[i]));
1166:
1167:                    if (i == (names.length - 1)
1168:                            && fTargetMethodBinding.isVarargs()) {
1169:                        newElement.setVarargs(true);
1170:                        if (typeBinding.isArray())
1171:                            typeBinding = typeBinding.getComponentType();
1172:                    }
1173:
1174:                    newElement.setType(rew.getImportRewrite().addImport(
1175:                            typeBinding, rew.getAST()));
1176:                    intermediary.parameters().add(newElement);
1177:                }
1178:            }
1179:
1180:            private void copyTypeParameters(MethodDeclaration intermediary,
1181:                    CompilationUnitRewrite rew) {
1182:                ITypeBinding[] typeParameters = fTargetMethodBinding
1183:                        .getTypeParameters();
1184:                for (int i = 0; i < typeParameters.length; i++) {
1185:                    ITypeBinding current = typeParameters[i];
1186:
1187:                    TypeParameter parameter = rew.getAST().newTypeParameter();
1188:                    parameter.setName(rew.getAST().newSimpleName(
1189:                            current.getName()));
1190:                    ITypeBinding[] bounds = current.getTypeBounds();
1191:                    for (int j = 0; j < bounds.length; j++)
1192:                        if (!"java.lang.Object".equals(bounds[j].getQualifiedName())) //$NON-NLS-1$
1193:                            parameter.typeBounds().add(
1194:                                    rew.getImportRewrite().addImport(bounds[j],
1195:                                            rew.getAST()));
1196:
1197:                    intermediary.typeParameters().add(parameter);
1198:                }
1199:            }
1200:
1201:            private void copyExceptions(MethodDeclaration intermediary,
1202:                    CompilationUnitRewrite imRewrite) {
1203:                ITypeBinding[] exceptionTypes = fTargetMethodBinding
1204:                        .getExceptionTypes();
1205:                for (int i = 0; i < exceptionTypes.length; i++) {
1206:                    final String qualifiedName = imRewrite.getImportRewrite()
1207:                            .addImport(exceptionTypes[i]);
1208:                    intermediary.thrownExceptions().add(
1209:                            ASTNodeFactory.newName(imRewrite.getAST(),
1210:                                    qualifiedName));
1211:                }
1212:            }
1213:
1214:            // ******************* UPDATE CALLS **********************
1215:
1216:            private RefactoringStatus updateMethodInvocation(
1217:                    MethodInvocation originalInvocation, IMember enclosing,
1218:                    CompilationUnitRewrite unitRewriter)
1219:                    throws JavaModelException {
1220:
1221:                RefactoringStatus status = new RefactoringStatus();
1222:
1223:                // If the method invocation utilizes type arguments, skip this
1224:                // call as the new target method may have additional parameters
1225:                if (originalInvocation.typeArguments().size() > 0)
1226:                    return createWarningAboutCall(
1227:                            enclosing,
1228:                            originalInvocation,
1229:                            RefactoringCoreMessages.IntroduceIndirectionRefactoring_call_warning_type_arguments);
1230:
1231:                MethodInvocation newInvocation = unitRewriter.getAST()
1232:                        .newMethodInvocation();
1233:                List newInvocationArgs = newInvocation.arguments();
1234:                List originalInvocationArgs = originalInvocation.arguments();
1235:
1236:                // static call => always use a qualifier
1237:                String qualifier = unitRewriter.getImportRewrite().addImport(
1238:                        fIntermediaryClassBinding);
1239:                newInvocation.setExpression(ASTNodeFactory.newName(unitRewriter
1240:                        .getAST(), qualifier));
1241:                newInvocation.setName(unitRewriter.getAST().newSimpleName(
1242:                        getIntermediaryMethodName()));
1243:
1244:                final Expression expression = originalInvocation
1245:                        .getExpression();
1246:
1247:                if (!isStaticTarget()) {
1248:                    // Add the expression as the first parameter
1249:                    if (expression == null) {
1250:                        // There is no expression for this call. Use a (possibly qualified) "this" expression.
1251:                        ThisExpression expr = unitRewriter.getAST()
1252:                                .newThisExpression();
1253:                        RefactoringStatus qualifierStatus = qualifyThisExpression(
1254:                                expr, originalInvocation, enclosing,
1255:                                unitRewriter);
1256:                        status.merge(qualifierStatus);
1257:                        if (qualifierStatus.hasEntries())
1258:                            // warning means don't include this invocation
1259:                            return status;
1260:                        newInvocationArgs.add(expr);
1261:                    } else {
1262:                        ASTNode expressionAsParam = unitRewriter
1263:                                .getASTRewrite().createMoveTarget(expression);
1264:                        newInvocationArgs.add(expressionAsParam);
1265:                    }
1266:                } else {
1267:                    if (expression != null) {
1268:                        // Check if expression is the class name. If not, there may
1269:                        // be side effects (e.g. inside methods) -> don't update
1270:                        if (!(expression instanceof  Name)
1271:                                || ASTNodes.getTypeBinding((Name) expression) == null)
1272:                            return createWarningAboutCall(
1273:                                    enclosing,
1274:                                    originalInvocation,
1275:                                    RefactoringCoreMessages.IntroduceIndirectionRefactoring_call_warning_static_expression_access);
1276:                    }
1277:                }
1278:
1279:                for (int i = 0; i < originalInvocationArgs.size(); i++) {
1280:                    Expression originalInvocationArg = (Expression) originalInvocationArgs
1281:                            .get(i);
1282:                    ASTNode movedArg = unitRewriter.getASTRewrite()
1283:                            .createMoveTarget(originalInvocationArg);
1284:                    newInvocationArgs.add(movedArg);
1285:                }
1286:
1287:                unitRewriter
1288:                        .getASTRewrite()
1289:                        .replace(
1290:                                originalInvocation,
1291:                                newInvocation,
1292:                                unitRewriter
1293:                                        .createGroupDescription(RefactoringCoreMessages.IntroduceIndirectionRefactoring_group_description_replace_call));
1294:
1295:                return status;
1296:            }
1297:
1298:            /**
1299:             * Attempts to qualify a "this" expression for a method invocation with an appropriate qualifier. 
1300:             * The invoked method is analyzed according to the following specs:
1301:             * 
1302:             * 'this' must be qualified iff method is declared in an enclosing type or a supertype of an enclosing type
1303:             * 
1304:             * 1) The method is declared somewhere outside of the cu of the invocation
1305:             *      1a) inside a supertype of the current type
1306:             *      1b) inside a supertype of an enclosing type
1307:             * 2) The method is declared inside of the cu of the invocation
1308:             * 		2a) inside the type of the invocation 
1309:             * 		2b) outside the type of the invocation
1310:             * 
1311:             * In case of 1a) and 2b), qualify with the enclosing type. 
1312:             * @param expr 
1313:             * @param originalInvocation 
1314:             * @param enclosing 
1315:             * @param unitRewriter 
1316:             * @return resulting status
1317:             * 
1318:             */
1319:            private RefactoringStatus qualifyThisExpression(
1320:                    ThisExpression expr, MethodInvocation originalInvocation,
1321:                    IMember enclosing, CompilationUnitRewrite unitRewriter) {
1322:
1323:                RefactoringStatus status = new RefactoringStatus();
1324:
1325:                IMethodBinding methodBinding = originalInvocation
1326:                        .resolveMethodBinding();
1327:                MethodDeclaration methodDeclaration = (MethodDeclaration) ASTNodes
1328:                        .findDeclaration(methodBinding, originalInvocation
1329:                                .getRoot());
1330:
1331:                ITypeBinding currentTypeBinding = null;
1332:                if (methodDeclaration != null) {
1333:                    // Case 1) : Declaring class is inside this cu => use its name if it's declared in an enclosing type
1334:                    if (ASTNodes.isParent(originalInvocation, methodDeclaration
1335:                            .getParent()))
1336:                        currentTypeBinding = methodBinding.getDeclaringClass();
1337:                    else
1338:                        currentTypeBinding = ASTNodes
1339:                                .getEnclosingType(originalInvocation);
1340:                } else {
1341:                    // Case 2) : Declaring class is outside of this cu => find subclass in this cu
1342:                    ASTNode currentTypeDeclaration = getEnclosingTypeDeclaration(originalInvocation);
1343:                    currentTypeBinding = ASTNodes
1344:                            .getEnclosingType(currentTypeDeclaration);
1345:                    while (currentTypeDeclaration != null
1346:                            && (Bindings.findMethodInHierarchy(
1347:                                    currentTypeBinding,
1348:                                    methodBinding.getName(), methodBinding
1349:                                            .getParameterTypes()) == null)) {
1350:                        currentTypeDeclaration = getEnclosingTypeDeclaration(currentTypeDeclaration
1351:                                .getParent());
1352:                        currentTypeBinding = ASTNodes
1353:                                .getEnclosingType(currentTypeDeclaration);
1354:                    }
1355:                }
1356:
1357:                if (currentTypeBinding == null) {
1358:                    status
1359:                            .merge(createWarningAboutCall(
1360:                                    enclosing,
1361:                                    originalInvocation,
1362:                                    RefactoringCoreMessages.IntroduceIndirectionRefactoring_call_warning_declaring_type_not_found));
1363:                    return status;
1364:                }
1365:
1366:                ITypeBinding typeOfCall = ASTNodes
1367:                        .getEnclosingType(originalInvocation);
1368:                if (!typeOfCall.equals(currentTypeBinding)) {
1369:                    if (currentTypeBinding.isAnonymous()) {
1370:                        // Cannot qualify, see bug 115277
1371:                        status
1372:                                .merge(createWarningAboutCall(
1373:                                        enclosing,
1374:                                        originalInvocation,
1375:                                        RefactoringCoreMessages.IntroduceIndirectionRefactoring_call_warning_anonymous_cannot_qualify));
1376:                    } else {
1377:                        expr.setQualifier(unitRewriter.getAST().newSimpleName(
1378:                                currentTypeBinding.getName()));
1379:                    }
1380:                } else {
1381:                    // do not qualify, only use "this.".
1382:                }
1383:
1384:                return status;
1385:            }
1386:
1387:            // ********* SMALL HELPERS ********************
1388:
1389:            /*
1390:             * Helper method for finding an IMethod inside a binding hierarchy
1391:             */
1392:            private IMethodBinding findMethodBindingInHierarchy(
1393:                    ITypeBinding currentTypeBinding, IMethod methodDeclaration) {
1394:                IMethodBinding[] bindings = currentTypeBinding
1395:                        .getDeclaredMethods();
1396:                for (int i = 0; i < bindings.length; i++)
1397:                    if (methodDeclaration.equals(bindings[i].getJavaElement()))
1398:                        return bindings[i];
1399:
1400:                ITypeBinding super Class = currentTypeBinding.getSuperclass();
1401:                if (super Class != null) {
1402:                    IMethodBinding b = findMethodBindingInHierarchy(super Class,
1403:                            methodDeclaration);
1404:                    if (b != null)
1405:                        return b;
1406:                }
1407:                ITypeBinding[] interfaces = currentTypeBinding.getInterfaces();
1408:                for (int i = 0; i < interfaces.length; i++) {
1409:                    IMethodBinding b = findMethodBindingInHierarchy(
1410:                            interfaces[i], methodDeclaration);
1411:                    if (b != null)
1412:                        return b;
1413:                }
1414:                return null;
1415:            }
1416:
1417:            /*
1418:             * Helper method for retrieving a *bottom-up* list of super type bindings
1419:             */
1420:            private ITypeBinding[] getTypeAndAllSuperTypes(ITypeBinding type) {
1421:                List result = new ArrayList();
1422:                collectSuperTypes(type, result);
1423:                return (ITypeBinding[]) result.toArray(new ITypeBinding[result
1424:                        .size()]);
1425:            }
1426:
1427:            private void collectSuperTypes(ITypeBinding curr, List list) {
1428:                if (list.add(curr.getTypeDeclaration())) {
1429:                    ITypeBinding[] interfaces = curr.getInterfaces();
1430:                    for (int i = 0; i < interfaces.length; i++) {
1431:                        collectSuperTypes(interfaces[i], list);
1432:                    }
1433:                    ITypeBinding super Class = curr.getSuperclass();
1434:                    if (super Class != null) {
1435:                        collectSuperTypes(super Class, list);
1436:                    }
1437:                }
1438:            }
1439:
1440:            private CompilationUnitRewrite getCachedCURewrite(
1441:                    ICompilationUnit unit) {
1442:                CompilationUnitRewrite rewrite = (CompilationUnitRewrite) fRewrites
1443:                        .get(unit);
1444:                if (rewrite == null) {
1445:                    rewrite = new CompilationUnitRewrite(unit);
1446:                    fRewrites.put(unit, rewrite);
1447:                }
1448:                return rewrite;
1449:            }
1450:
1451:            private boolean isRewriteKept(ICompilationUnit compilationUnit) {
1452:                return fIntermediaryClass.getCompilationUnit().equals(
1453:                        compilationUnit);
1454:            }
1455:
1456:            private void createChangeAndDiscardRewrite(
1457:                    ICompilationUnit compilationUnit) throws CoreException {
1458:                CompilationUnitRewrite rewrite = (CompilationUnitRewrite) fRewrites
1459:                        .get(compilationUnit);
1460:                if (rewrite != null) {
1461:                    fTextChangeManager.manage(compilationUnit, rewrite
1462:                            .createChange());
1463:                    fRewrites.remove(compilationUnit);
1464:                }
1465:            }
1466:
1467:            private SearchResultGroup[] getReferences(IMethod[] methods,
1468:                    IProgressMonitor pm, RefactoringStatus status)
1469:                    throws CoreException {
1470:                SearchPattern pattern = RefactoringSearchEngine
1471:                        .createOrPattern(methods,
1472:                                IJavaSearchConstants.REFERENCES);
1473:                IJavaSearchScope scope = RefactoringScopeFactory.create(
1474:                        fIntermediaryClass, false);
1475:                return RefactoringSearchEngine.search(pattern, scope, pm,
1476:                        status);
1477:            }
1478:
1479:            private ITypeBinding typeToBinding(IType type, CompilationUnit root)
1480:                    throws JavaModelException {
1481:                ASTNode typeNode = typeToDeclaration(type, root);
1482:                if (type.isAnonymous()) {
1483:                    return ((AnonymousClassDeclaration) typeNode)
1484:                            .resolveBinding();
1485:                } else {
1486:                    return ((AbstractTypeDeclaration) typeNode)
1487:                            .resolveBinding();
1488:                }
1489:            }
1490:
1491:            private ASTNode typeToDeclaration(IType type, CompilationUnit root)
1492:                    throws JavaModelException {
1493:                Name intermediateName = (Name) NodeFinder.perform(root, type
1494:                        .getNameRange());
1495:                if (type.isAnonymous()) {
1496:                    return ASTNodes.getParent(intermediateName,
1497:                            AnonymousClassDeclaration.class);
1498:                } else {
1499:                    return ASTNodes.getParent(intermediateName,
1500:                            AbstractTypeDeclaration.class);
1501:                }
1502:            }
1503:
1504:            private ASTNode getEnclosingTypeDeclaration(ASTNode node) {
1505:                while (node != null) {
1506:                    if (node instanceof  AbstractTypeDeclaration) {
1507:                        return node;
1508:                    } else if (node instanceof  AnonymousClassDeclaration) {
1509:                        return node;
1510:                    }
1511:                    node = node.getParent();
1512:                }
1513:                return null;
1514:            }
1515:
1516:            private ChildListPropertyDescriptor typeToBodyDeclarationProperty(
1517:                    IType type, CompilationUnit root) throws JavaModelException {
1518:                ASTNode typeDeclaration = typeToDeclaration(type, root);
1519:                if (typeDeclaration instanceof  AbstractTypeDeclaration)
1520:                    return ((AbstractTypeDeclaration) typeDeclaration)
1521:                            .getBodyDeclarationsProperty();
1522:                else if (typeDeclaration instanceof  AnonymousClassDeclaration)
1523:                    return AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY;
1524:
1525:                Assert.isTrue(false);
1526:                return null;
1527:            }
1528:
1529:            private RefactoringStatus createWarningAboutCall(IMember enclosing,
1530:                    ASTNode concreteNode, String message) {
1531:                String name = JavaElementLabels.getElementLabel(enclosing,
1532:                        JavaElementLabels.ALL_DEFAULT);
1533:                String container = JavaElementLabels.getElementLabel(enclosing
1534:                        .getDeclaringType(),
1535:                        JavaElementLabels.ALL_FULLY_QUALIFIED);
1536:                return RefactoringStatus.createWarningStatus(Messages.format(
1537:                        message, new String[] { name, container }),
1538:                        JavaStatusContext.create(
1539:                                enclosing.getCompilationUnit(), concreteNode));
1540:            }
1541:
1542:            private ITypeBinding getExpressionType(MethodInvocation invocation) {
1543:                Expression expression = invocation.getExpression();
1544:                ITypeBinding typeBinding = null;
1545:                if (expression == null) {
1546:                    typeBinding = invocation.resolveMethodBinding()
1547:                            .getDeclaringClass();
1548:                } else {
1549:                    typeBinding = expression.resolveTypeBinding();
1550:                }
1551:
1552:                Assert.isNotNull(typeBinding,
1553:                        "Type binding of target expression may not be null"); //$NON-NLS-1$
1554:                return typeBinding;
1555:            }
1556:
1557:            private IFile[] getAllFilesToModify() {
1558:                List cus = new ArrayList();
1559:                cus.addAll(Arrays.asList(fTextChangeManager
1560:                        .getAllCompilationUnits()));
1561:                return ResourceUtil.getFiles((ICompilationUnit[]) cus
1562:                        .toArray(new ICompilationUnit[cus.size()]));
1563:            }
1564:
1565:            private boolean isStaticTarget() throws JavaModelException {
1566:                return Flags.isStatic(fTargetMethod.getFlags());
1567:            }
1568:
1569:            private IMember getEnclosingInitialSelectionMember()
1570:                    throws JavaModelException {
1571:                return (IMember) fSelectionCompilationUnit
1572:                        .getElementAt(fSelectionStart);
1573:            }
1574:
1575:            private static ASTNode getSelectedNode(ICompilationUnit unit,
1576:                    CompilationUnit root, int offset, int length) {
1577:                ASTNode node = null;
1578:                try {
1579:                    if (unit != null)
1580:                        node = checkNode(NodeFinder.perform(root, offset,
1581:                                length, unit));
1582:                    else
1583:                        node = checkNode(NodeFinder.perform(root, offset,
1584:                                length));
1585:                } catch (JavaModelException e) {
1586:                    // Do nothing
1587:                }
1588:                if (node != null)
1589:                    return node;
1590:                return checkNode(NodeFinder.perform(root, offset, length));
1591:            }
1592:
1593:            private static ASTNode checkNode(ASTNode node) {
1594:                if (node == null)
1595:                    return null;
1596:                if (node.getNodeType() == ASTNode.SIMPLE_NAME) {
1597:                    node = node.getParent();
1598:                } else if (node.getNodeType() == ASTNode.EXPRESSION_STATEMENT) {
1599:                    node = ((ExpressionStatement) node).getExpression();
1600:                }
1601:                switch (node.getNodeType()) {
1602:                case ASTNode.METHOD_INVOCATION:
1603:                case ASTNode.METHOD_DECLARATION:
1604:                case ASTNode.SUPER_METHOD_INVOCATION:
1605:                    return node;
1606:                }
1607:                return null;
1608:            }
1609:
1610:            // ***************** VISIBILITY ********************
1611:
1612:            private ModifierKeyword getNeededVisibility(IMember whoToAdjust,
1613:                    IMember fromWhereToLook) throws JavaModelException {
1614:                return fAdjustor.getVisibilityThreshold(fromWhereToLook,
1615:                        whoToAdjust, new NullProgressMonitor());
1616:            }
1617:
1618:            private RefactoringStatus adjustVisibility(IMember whoToAdjust,
1619:                    IMember fromWhereToLook, IProgressMonitor monitor)
1620:                    throws CoreException {
1621:                return adjustVisibility(whoToAdjust, getNeededVisibility(
1622:                        whoToAdjust, fromWhereToLook), true, monitor);
1623:            }
1624:
1625:            private RefactoringStatus adjustVisibility(IMember whoToAdjust,
1626:                    ModifierKeyword neededVisibility, IProgressMonitor monitor)
1627:                    throws CoreException {
1628:                return adjustVisibility(whoToAdjust, neededVisibility, false,
1629:                        monitor);
1630:            }
1631:
1632:            private RefactoringStatus adjustVisibility(IMember whoToAdjust,
1633:                    ModifierKeyword neededVisibility,
1634:                    boolean alsoIncreaseEnclosing, IProgressMonitor monitor)
1635:                    throws CoreException {
1636:
1637:                Map adjustments;
1638:                if (isRewriteKept(whoToAdjust.getCompilationUnit()))
1639:                    adjustments = fIntermediaryAdjustments;
1640:                else
1641:                    adjustments = new HashMap();
1642:
1643:                int existingAdjustments = adjustments.size();
1644:                addAdjustment(whoToAdjust, neededVisibility, adjustments);
1645:
1646:                if (alsoIncreaseEnclosing)
1647:                    while (whoToAdjust.getDeclaringType() != null) {
1648:                        whoToAdjust = whoToAdjust.getDeclaringType();
1649:                        addAdjustment(whoToAdjust, neededVisibility,
1650:                                adjustments);
1651:                    }
1652:
1653:                boolean hasNewAdjustments = (adjustments.size() - existingAdjustments) > 0;
1654:                if (hasNewAdjustments
1655:                        && ((whoToAdjust.isReadOnly() || whoToAdjust.isBinary())))
1656:                    return RefactoringStatus
1657:                            .createErrorStatus(
1658:                                    Messages
1659:                                            .format(
1660:                                                    RefactoringCoreMessages.IntroduceIndirectionRefactoring_cannot_update_binary_target_visibility,
1661:                                                    new String[] { JavaElementLabels
1662:                                                            .getElementLabel(
1663:                                                                    whoToAdjust,
1664:                                                                    JavaElementLabels.ALL_DEFAULT) }),
1665:                                    JavaStatusContext.create(whoToAdjust));
1666:
1667:                RefactoringStatus status = new RefactoringStatus();
1668:
1669:                // Don't create a rewrite if it is not necessary
1670:                if (!hasNewAdjustments)
1671:                    return status;
1672:
1673:                try {
1674:                    monitor
1675:                            .beginTask(
1676:                                    RefactoringCoreMessages.MemberVisibilityAdjustor_adjusting,
1677:                                    2);
1678:                    Map rewrites;
1679:                    if (!isRewriteKept(whoToAdjust.getCompilationUnit())) {
1680:                        CompilationUnitRewrite rewrite = new CompilationUnitRewrite(
1681:                                whoToAdjust.getCompilationUnit());
1682:                        rewrite.setResolveBindings(false);
1683:                        rewrites = new HashMap();
1684:                        rewrites.put(whoToAdjust.getCompilationUnit(), rewrite);
1685:                        status
1686:                                .merge(rewriteVisibility(
1687:                                        adjustments,
1688:                                        rewrites,
1689:                                        new SubProgressMonitor(
1690:                                                monitor,
1691:                                                1,
1692:                                                SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)));
1693:                        rewrite
1694:                                .attachChange(
1695:                                        (CompilationUnitChange) fTextChangeManager
1696:                                                .get(whoToAdjust
1697:                                                        .getCompilationUnit()),
1698:                                        true,
1699:                                        new SubProgressMonitor(
1700:                                                monitor,
1701:                                                1,
1702:                                                SubProgressMonitor.SUPPRESS_SUBTASK_LABEL));
1703:                    }
1704:                } finally {
1705:                    monitor.done();
1706:                }
1707:                return status;
1708:            }
1709:
1710:            private RefactoringStatus rewriteVisibility(Map adjustments,
1711:                    Map rewrites, IProgressMonitor monitor)
1712:                    throws JavaModelException {
1713:                RefactoringStatus status = new RefactoringStatus();
1714:                fAdjustor.setRewrites(rewrites);
1715:                fAdjustor.setAdjustments(adjustments);
1716:                fAdjustor.setStatus(status);
1717:                fAdjustor.rewriteVisibility(monitor);
1718:                return status;
1719:            }
1720:
1721:            private void addAdjustment(IMember whoToAdjust,
1722:                    ModifierKeyword neededVisibility, Map adjustments)
1723:                    throws JavaModelException {
1724:                ModifierKeyword currentVisibility = ModifierKeyword
1725:                        .fromFlagValue(JdtFlags.getVisibilityCode(whoToAdjust));
1726:                if (MemberVisibilityAdjustor.hasLowerVisibility(
1727:                        currentVisibility, neededVisibility)
1728:                        && MemberVisibilityAdjustor.needsVisibilityAdjustments(
1729:                                whoToAdjust, neededVisibility, adjustments))
1730:                    adjustments
1731:                            .put(
1732:                                    whoToAdjust,
1733:                                    new MemberVisibilityAdjustor.IncomingMemberVisibilityAdjustment(
1734:                                            whoToAdjust,
1735:                                            neededVisibility,
1736:                                            RefactoringStatus
1737:                                                    .createWarningStatus(
1738:                                                            Messages
1739:                                                                    .format(
1740:                                                                            MemberVisibilityAdjustor
1741:                                                                                    .getMessage(whoToAdjust),
1742:                                                                            new String[] {
1743:                                                                                    MemberVisibilityAdjustor
1744:                                                                                            .getLabel(whoToAdjust),
1745:                                                                                    MemberVisibilityAdjustor
1746:                                                                                            .getLabel(neededVisibility) }),
1747:                                                            JavaStatusContext
1748:                                                                    .create(whoToAdjust))));
1749:            }
1750:
1751:            public RefactoringStatus initialize(
1752:                    final RefactoringArguments arguments) {
1753:                if (arguments instanceof  JavaRefactoringArguments) {
1754:                    final JavaRefactoringArguments extended = (JavaRefactoringArguments) arguments;
1755:                    String handle = extended
1756:                            .getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
1757:                    if (handle != null) {
1758:                        final IJavaElement element = JavaRefactoringDescriptorUtil
1759:                                .handleToElement(extended.getProject(), handle,
1760:                                        false);
1761:                        if (element == null
1762:                                || !element.exists()
1763:                                || element.getElementType() != IJavaElement.METHOD)
1764:                            return createInputFatalStatus(element,
1765:                                    IJavaRefactorings.INTRODUCE_INDIRECTION);
1766:                        else
1767:                            fTargetMethod = (IMethod) element;
1768:                    } else
1769:                        return RefactoringStatus
1770:                                .createFatalErrorStatus(Messages
1771:                                        .format(
1772:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1773:                                                JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
1774:                    handle = extended
1775:                            .getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + 1);
1776:                    if (handle != null) {
1777:                        final IJavaElement element = JavaRefactoringDescriptorUtil
1778:                                .handleToElement(extended.getProject(), handle,
1779:                                        false);
1780:                        if (element == null
1781:                                || !element.exists()
1782:                                || element.getElementType() != IJavaElement.TYPE)
1783:                            return createInputFatalStatus(element,
1784:                                    IJavaRefactorings.INTRODUCE_INDIRECTION);
1785:                        else
1786:                            fIntermediaryClass = (IType) element;
1787:                    } else
1788:                        return RefactoringStatus
1789:                                .createFatalErrorStatus(Messages
1790:                                        .format(
1791:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1792:                                                JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + 1));
1793:                    final String references = extended
1794:                            .getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_REFERENCES);
1795:                    if (references != null) {
1796:                        fUpdateReferences = Boolean.valueOf(references)
1797:                                .booleanValue();
1798:                    } else
1799:                        return RefactoringStatus
1800:                                .createFatalErrorStatus(Messages
1801:                                        .format(
1802:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1803:                                                JavaRefactoringDescriptorUtil.ATTRIBUTE_REFERENCES));
1804:                    final String name = extended
1805:                            .getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME);
1806:                    if (name != null && !"".equals(name)) //$NON-NLS-1$
1807:                        return setIntermediaryMethodName(name);
1808:                    else
1809:                        return RefactoringStatus
1810:                                .createFatalErrorStatus(Messages
1811:                                        .format(
1812:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1813:                                                JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME));
1814:                } else
1815:                    return RefactoringStatus
1816:                            .createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
1817:            }
1818:        }
w_w_w___.___j_a_v__a___2_s___._c___o_m___ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.