Source Code Cross Referenced for IntroduceFactoryRefactoring.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.util.ArrayList;
0013:        import java.util.Collection;
0014:        import java.util.HashMap;
0015:        import java.util.Iterator;
0016:        import java.util.List;
0017:        import java.util.Map;
0018:        import java.util.StringTokenizer;
0019:
0020:        import org.eclipse.text.edits.MultiTextEdit;
0021:        import org.eclipse.text.edits.TextEditGroup;
0022:
0023:        import org.eclipse.core.runtime.Assert;
0024:        import org.eclipse.core.runtime.CoreException;
0025:        import org.eclipse.core.runtime.IProgressMonitor;
0026:        import org.eclipse.core.runtime.IStatus;
0027:        import org.eclipse.core.runtime.NullProgressMonitor;
0028:        import org.eclipse.core.runtime.OperationCanceledException;
0029:        import org.eclipse.core.runtime.SubProgressMonitor;
0030:
0031:        import org.eclipse.ltk.core.refactoring.Change;
0032:        import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
0033:        import org.eclipse.ltk.core.refactoring.RefactoringStatus;
0034:        import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
0035:
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.IMethod;
0040:        import org.eclipse.jdt.core.IType;
0041:        import org.eclipse.jdt.core.JavaModelException;
0042:        import org.eclipse.jdt.core.dom.AST;
0043:        import org.eclipse.jdt.core.dom.ASTNode;
0044:        import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
0045:        import org.eclipse.jdt.core.dom.Block;
0046:        import org.eclipse.jdt.core.dom.ClassInstanceCreation;
0047:        import org.eclipse.jdt.core.dom.CompilationUnit;
0048:        import org.eclipse.jdt.core.dom.ConstructorInvocation;
0049:        import org.eclipse.jdt.core.dom.Expression;
0050:        import org.eclipse.jdt.core.dom.ExpressionStatement;
0051:        import org.eclipse.jdt.core.dom.IMethodBinding;
0052:        import org.eclipse.jdt.core.dom.ITypeBinding;
0053:        import org.eclipse.jdt.core.dom.MethodDeclaration;
0054:        import org.eclipse.jdt.core.dom.MethodInvocation;
0055:        import org.eclipse.jdt.core.dom.MethodRef;
0056:        import org.eclipse.jdt.core.dom.Modifier;
0057:        import org.eclipse.jdt.core.dom.Name;
0058:        import org.eclipse.jdt.core.dom.ParameterizedType;
0059:        import org.eclipse.jdt.core.dom.ReturnStatement;
0060:        import org.eclipse.jdt.core.dom.SimpleName;
0061:        import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
0062:        import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
0063:        import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
0064:        import org.eclipse.jdt.core.dom.Type;
0065:        import org.eclipse.jdt.core.dom.TypeParameter;
0066:        import org.eclipse.jdt.core.dom.VariableDeclaration;
0067:        import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
0068:        import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
0069:        import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
0070:        import org.eclipse.jdt.core.refactoring.descriptors.IntroduceFactoryDescriptor;
0071:        import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
0072:        import org.eclipse.jdt.core.search.IJavaSearchConstants;
0073:        import org.eclipse.jdt.core.search.IJavaSearchScope;
0074:        import org.eclipse.jdt.core.search.SearchMatch;
0075:        import org.eclipse.jdt.core.search.SearchPattern;
0076:
0077:        import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
0078:        import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
0079:        import org.eclipse.jdt.internal.corext.dom.ASTNodes;
0080:        import org.eclipse.jdt.internal.corext.dom.Bindings;
0081:        import org.eclipse.jdt.internal.corext.dom.ModifierRewrite;
0082:        import org.eclipse.jdt.internal.corext.dom.NodeFinder;
0083:        import org.eclipse.jdt.internal.corext.refactoring.Checks;
0084:        import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
0085:        import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
0086:        import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
0087:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
0088:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory;
0089:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine2;
0090:        import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
0091:        import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange;
0092:        import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
0093:        import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationStateChange;
0094:        import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ASTCreator;
0095:        import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
0096:        import org.eclipse.jdt.internal.corext.util.JdtFlags;
0097:        import org.eclipse.jdt.internal.corext.util.Messages;
0098:        import org.eclipse.jdt.internal.corext.util.SearchUtils;
0099:
0100:        import org.eclipse.jdt.ui.JavaElementLabels;
0101:
0102:        import org.eclipse.jdt.internal.ui.JavaUIStatus;
0103:        import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
0104:
0105:        /**
0106:         * Refactoring class that permits the substitution of a factory method
0107:         * for direct calls to a given constructor.
0108:         * @author rfuhrer
0109:         */
0110:        public class IntroduceFactoryRefactoring extends ScriptableRefactoring {
0111:
0112:            private static final String ATTRIBUTE_PROTECT = "protect"; //$NON-NLS-1$
0113:
0114:            /**
0115:             * The handle for the compilation unit holding the selection that was
0116:             * passed into this refactoring.
0117:             */
0118:            private ICompilationUnit fCUHandle;
0119:
0120:            /**
0121:             * The AST for the compilation unit holding the selection that was
0122:             * passed into this refactoring.
0123:             */
0124:            private CompilationUnit fCU;
0125:
0126:            /**
0127:             * Handle for compilation unit in which the factory method/class/interface will be
0128:             * generated.
0129:             */
0130:            private ICompilationUnit fFactoryUnitHandle;
0131:
0132:            /**
0133:             * The start of the original textual selection in effect when this refactoring
0134:             * was initiated. If the refactoring was initiated from a structured selection
0135:             * (e.g. from the outline view), then this refers to the textual selection that
0136:             * corresponds to the structured selection item.
0137:             */
0138:            private int fSelectionStart;
0139:
0140:            /**
0141:             * The length of the original textual selection in effect when this refactoring
0142:             * was initiated. If the refactoring was initiated from a structured selection
0143:             * (e.g. from the outline view), then this refers to the textual selection that
0144:             * corresponds to the structured selection item.
0145:             */
0146:            private int fSelectionLength;
0147:
0148:            /**
0149:             * The AST node corresponding to the user's textual selection.
0150:             */
0151:            private ASTNode fSelectedNode;
0152:
0153:            /**
0154:             * The method binding for the selected constructor.
0155:             */
0156:            private IMethodBinding fCtorBinding;
0157:
0158:            /**
0159:             * <code>TypeDeclaration</code> for class containing the constructor to be
0160:             * encapsulated.
0161:             */
0162:            private AbstractTypeDeclaration fCtorOwningClass;
0163:
0164:            /**
0165:             * The name to be given to the generated factory method.
0166:             */
0167:            private String fNewMethodName = null;
0168:
0169:            /**
0170:             * An array of <code>SearchResultGroup</code>'s of all call sites
0171:             * that refer to the constructor signature in question.
0172:             */
0173:            private SearchResultGroup[] fAllCallsTo;
0174:
0175:            /**
0176:             * The class that will own the factory method/class/interface.
0177:             */
0178:            private AbstractTypeDeclaration fFactoryOwningClass;
0179:
0180:            /**
0181:             * The newly-generated factory method.
0182:             */
0183:            private MethodDeclaration fFactoryMethod = null;
0184:
0185:            /**
0186:             * An array containing the names of the constructor's formal arguments,
0187:             * if available, otherwise "arg1" ... "argN".
0188:             */
0189:            private String[] fFormalArgNames = null;
0190:
0191:            /**
0192:             * An array of <code>ITypeBinding</code>'s that describes the types of
0193:             * the constructor arguments, in order.
0194:             */
0195:            private ITypeBinding[] fArgTypes;
0196:
0197:            /**
0198:             * True iff the given constructor has a varargs signature.
0199:             */
0200:            private boolean fCtorIsVarArgs;
0201:
0202:            /**
0203:             * If true, change the visibility of the constructor to protected to better
0204:             * encapsulate it.
0205:             */
0206:            private boolean fProtectConstructor = true;
0207:
0208:            /**
0209:             * An <code>ImportRewrite</code> that manages imports needed to satisfy
0210:             * newly-introduced type references in the <code>ICompilationUnit</code>
0211:             * currently being rewritten during <code>createChange()</code>.
0212:             */
0213:            private ImportRewrite fImportRewriter;
0214:
0215:            /**
0216:             * True iff there are call sites for the constructor to be encapsulated
0217:             * located in binary classes.
0218:             */
0219:            private boolean fCallSitesInBinaryUnits;
0220:
0221:            /**
0222:             * <code>CompilationUnit</code> in which the factory is to be created.
0223:             */
0224:            private CompilationUnit fFactoryCU;
0225:
0226:            /**
0227:             * The fully qualified name of the factory class. This is only used
0228:             * if invoked from a refactoring script.
0229:             */
0230:            private String fFactoryClassName;
0231:
0232:            private int fConstructorVisibility = Modifier.PRIVATE;
0233:
0234:            /**
0235:             * Creates a new <code>IntroduceFactoryRefactoring</code> with the given selection
0236:             * on the given compilation unit.
0237:             * @param cu the <code>ICompilationUnit</code> in which the user selection was made, or <code>null</code> if invoked from scripting
0238:             * @param selectionStart the start of the textual selection in <code>cu</code>
0239:             * @param selectionLength the length of the textual selection in <code>cu</code>
0240:             */
0241:            public IntroduceFactoryRefactoring(ICompilationUnit cu,
0242:                    int selectionStart, int selectionLength) {
0243:                Assert.isTrue(selectionStart >= 0);
0244:                Assert.isTrue(selectionLength >= 0);
0245:                fSelectionStart = selectionStart;
0246:                fSelectionLength = selectionLength;
0247:                fCUHandle = cu;
0248:                if (cu != null)
0249:                    initialize();
0250:            }
0251:
0252:            private void initialize() {
0253:                fCU = ASTCreator.createAST(fCUHandle, null);
0254:            }
0255:
0256:            /**
0257:             * Finds and returns the <code>ASTNode</code> for the given source text
0258:             * selection, if it is an entire constructor call or the class name portion
0259:             * of a constructor call or constructor declaration, or null otherwise.
0260:             * @param unit The compilation unit in which the selection was made 
0261:             * @param offset The textual offset of the start of the selection
0262:             * @param length The length of the selection in characters
0263:             * @return ClassInstanceCreation or MethodDeclaration
0264:             */
0265:            private ASTNode getTargetNode(ICompilationUnit unit, int offset,
0266:                    int length) {
0267:                ASTNode node = ASTNodes.getNormalizedNode(NodeFinder.perform(
0268:                        fCU, offset, length));
0269:                if (node.getNodeType() == ASTNode.CLASS_INSTANCE_CREATION)
0270:                    return node;
0271:                if (node.getNodeType() == ASTNode.METHOD_DECLARATION
0272:                        && ((MethodDeclaration) node).isConstructor())
0273:                    return node;
0274:                // we have some sub node. Make sure its the right child of the parent
0275:                StructuralPropertyDescriptor location = node
0276:                        .getLocationInParent();
0277:                ASTNode parent = node.getParent();
0278:                if (location == ClassInstanceCreation.TYPE_PROPERTY) {
0279:                    return parent;
0280:                } else if (location == MethodDeclaration.NAME_PROPERTY
0281:                        && ((MethodDeclaration) parent).isConstructor()) {
0282:                    return parent;
0283:                }
0284:                return null;
0285:            }
0286:
0287:            /**
0288:             * Determines what kind of AST node was selected, and returns an error status
0289:             * if the kind of node is inappropriate for this refactoring.
0290:             * @param pm
0291:             * @return a RefactoringStatus indicating whether the selection is valid
0292:             * @throws JavaModelException
0293:             */
0294:            private RefactoringStatus checkSelection(IProgressMonitor pm)
0295:                    throws JavaModelException {
0296:                try {
0297:                    pm
0298:                            .beginTask(
0299:                                    RefactoringCoreMessages.IntroduceFactory_examiningSelection,
0300:                                    2);
0301:
0302:                    fSelectedNode = getTargetNode(fCUHandle, fSelectionStart,
0303:                            fSelectionLength);
0304:
0305:                    if (fSelectedNode == null)
0306:                        return RefactoringStatus
0307:                                .createFatalErrorStatus(RefactoringCoreMessages.IntroduceFactory_notAConstructorInvocation);
0308:
0309:                    // getTargetNode() must return either a ClassInstanceCreation or a
0310:                    // constructor MethodDeclaration; nothing else.
0311:                    if (fSelectedNode instanceof  ClassInstanceCreation) {
0312:                        ClassInstanceCreation classInstanceCreation = (ClassInstanceCreation) fSelectedNode;
0313:                        fCtorBinding = classInstanceCreation
0314:                                .resolveConstructorBinding();
0315:                    } else if (fSelectedNode instanceof  MethodDeclaration) {
0316:                        MethodDeclaration methodDeclaration = (MethodDeclaration) fSelectedNode;
0317:                        fCtorBinding = methodDeclaration.resolveBinding();
0318:                    }
0319:
0320:                    if (fCtorBinding == null)
0321:                        return RefactoringStatus
0322:                                .createFatalErrorStatus(RefactoringCoreMessages.IntroduceFactory_unableToResolveConstructorBinding);
0323:
0324:                    // If this constructor is of a generic type, get the generic version,
0325:                    // not some instantiation thereof.
0326:                    fCtorBinding = fCtorBinding.getMethodDeclaration();
0327:
0328:                    if (fNewMethodName == null)
0329:                        fNewMethodName = "create" + fCtorBinding.getName();//$NON-NLS-1$
0330:
0331:                    pm.worked(1);
0332:
0333:                    // We don't handle constructors of nested types at the moment
0334:                    if (fCtorBinding.getDeclaringClass().isNested())
0335:                        return RefactoringStatus
0336:                                .createFatalErrorStatus(RefactoringCoreMessages.IntroduceFactory_unsupportedNestedTypes);
0337:
0338:                    ITypeBinding ctorType = fCtorBinding.getDeclaringClass();
0339:                    IType ctorOwningType = (IType) ctorType.getJavaElement();
0340:
0341:                    if (ctorOwningType.isBinary())
0342:                        // Can't modify binary CU; don't know what CU to put factory method
0343:                        return RefactoringStatus
0344:                                .createFatalErrorStatus(RefactoringCoreMessages.IntroduceFactory_constructorInBinaryClass);
0345:                    if (ctorOwningType.isEnum())
0346:                        // Doesn't make sense to encapsulate enum constructors
0347:                        return RefactoringStatus
0348:                                .createFatalErrorStatus(RefactoringCoreMessages.IntroduceFactory_constructorInEnum);
0349:
0350:                    // Put the generated factory method inside the type that owns the constructor
0351:                    fFactoryUnitHandle = ctorOwningType.getCompilationUnit();
0352:                    fFactoryCU = getASTFor(fFactoryUnitHandle);
0353:
0354:                    Name ctorOwnerName = (Name) NodeFinder.perform(fFactoryCU,
0355:                            ctorOwningType.getNameRange());
0356:
0357:                    fCtorOwningClass = (AbstractTypeDeclaration) ASTNodes
0358:                            .getParent(ctorOwnerName,
0359:                                    AbstractTypeDeclaration.class);
0360:                    fFactoryOwningClass = fCtorOwningClass;
0361:
0362:                    pm.worked(1);
0363:
0364:                    return new RefactoringStatus();
0365:                } finally {
0366:                    pm.done();
0367:                }
0368:            }
0369:
0370:            /*
0371:             * @see org.eclipse.jdt.internal.corext.refactoring.base.Refactoring#checkActivation(org.eclipse.core.runtime.IProgressMonitor)
0372:             */
0373:            public RefactoringStatus checkInitialConditions(IProgressMonitor pm)
0374:                    throws CoreException {
0375:                try {
0376:                    pm
0377:                            .beginTask(
0378:                                    RefactoringCoreMessages.IntroduceFactory_checkingActivation,
0379:                                    1);
0380:
0381:                    if (!fCUHandle.isStructureKnown())
0382:                        return RefactoringStatus
0383:                                .createFatalErrorStatus(RefactoringCoreMessages.IntroduceFactory_syntaxError);
0384:
0385:                    return checkSelection(new SubProgressMonitor(pm, 1));
0386:                } finally {
0387:                    pm.done();
0388:                }
0389:            }
0390:
0391:            /**
0392:             * @param searchHits 
0393:             * @return the set of compilation units that will be affected by this
0394:             * particular invocation of this refactoring. This in general includes
0395:             * the class containing the constructor in question, as well as all
0396:             * call sites to the constructor.
0397:             */
0398:            private ICompilationUnit[] collectAffectedUnits(
0399:                    SearchResultGroup[] searchHits) {
0400:                Collection result = new ArrayList();
0401:                boolean hitInFactoryClass = false;
0402:
0403:                for (int i = 0; i < searchHits.length; i++) {
0404:                    SearchResultGroup rg = searchHits[i];
0405:                    ICompilationUnit icu = rg.getCompilationUnit();
0406:
0407:                    result.add(icu);
0408:                    if (icu.equals(fFactoryUnitHandle))
0409:                        hitInFactoryClass = true;
0410:                }
0411:                if (!hitInFactoryClass)
0412:                    result.add(fFactoryUnitHandle);
0413:                return (ICompilationUnit[]) result
0414:                        .toArray(new ICompilationUnit[result.size()]);
0415:            }
0416:
0417:            /**
0418:             * @param ctor 
0419:             * @param methodBinding 
0420:             * @return a <code>SearchPattern</code> that finds all calls to the constructor
0421:             * identified by the argument <code>methodBinding</code>.
0422:             */
0423:            private SearchPattern createSearchPattern(IMethod ctor,
0424:                    IMethodBinding methodBinding) {
0425:                Assert
0426:                        .isNotNull(
0427:                                methodBinding,
0428:                                RefactoringCoreMessages.IntroduceFactory_noBindingForSelectedConstructor);
0429:
0430:                if (ctor != null)
0431:                    return SearchPattern.createPattern(ctor,
0432:                            IJavaSearchConstants.REFERENCES,
0433:                            SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
0434:                else { // perhaps a synthetic method? (but apparently not always... hmmm...)
0435:                    // Can't find an IMethod for this method, so build a string pattern instead
0436:                    StringBuffer buf = new StringBuffer();
0437:
0438:                    buf.append(
0439:                            methodBinding.getDeclaringClass()
0440:                                    .getQualifiedName()).append("(");//$NON-NLS-1$
0441:                    for (int i = 0; i < fArgTypes.length; i++) {
0442:                        if (i != 0)
0443:                            buf.append(","); //$NON-NLS-1$
0444:                        buf.append(fArgTypes[i].getQualifiedName());
0445:                    }
0446:                    buf.append(")"); //$NON-NLS-1$
0447:                    return SearchPattern.createPattern(buf.toString(),
0448:                            IJavaSearchConstants.CONSTRUCTOR,
0449:                            IJavaSearchConstants.REFERENCES,
0450:                            SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
0451:                }
0452:            }
0453:
0454:            private IJavaSearchScope createSearchScope(IMethod ctor,
0455:                    IMethodBinding binding) throws JavaModelException {
0456:                if (ctor != null) {
0457:                    return RefactoringScopeFactory.create(ctor);
0458:                } else {
0459:                    ITypeBinding type = Bindings.getTopLevelType(binding
0460:                            .getDeclaringClass());
0461:                    return RefactoringScopeFactory
0462:                            .create(type.getJavaElement());
0463:                }
0464:            }
0465:
0466:            /**
0467:             * @param groups 
0468:             * @return an array of <code>SearchResultGroup</code>'s like the argument,
0469:             * but omitting those groups that have no corresponding compilation unit
0470:             * (i.e. are binary and therefore can't be modified).
0471:             */
0472:            private SearchResultGroup[] excludeBinaryUnits(
0473:                    SearchResultGroup[] groups) {
0474:                Collection/*<SearchResultGroup>*/result = new ArrayList();
0475:
0476:                for (int i = 0; i < groups.length; i++) {
0477:                    SearchResultGroup rg = groups[i];
0478:                    ICompilationUnit unit = rg.getCompilationUnit();
0479:
0480:                    if (unit != null) // Ignore hits within a binary unit
0481:                        result.add(rg);
0482:                    else
0483:                        fCallSitesInBinaryUnits = true;
0484:                }
0485:                return (SearchResultGroup[]) result
0486:                        .toArray(new SearchResultGroup[result.size()]);
0487:            }
0488:
0489:            /**
0490:             * Search for all calls to the given <code>IMethodBinding</code> in the project
0491:             * that contains the compilation unit <code>fCUHandle</code>.
0492:             * @param methodBinding
0493:             * @param pm
0494:             * @param status
0495:             * @return an array of <code>SearchResultGroup</code>'s that identify the search matches
0496:             * @throws JavaModelException
0497:             */
0498:            private SearchResultGroup[] searchForCallsTo(
0499:                    IMethodBinding methodBinding, IProgressMonitor pm,
0500:                    RefactoringStatus status) throws JavaModelException {
0501:                IMethod method = (IMethod) methodBinding.getJavaElement();
0502:                final RefactoringSearchEngine2 engine = new RefactoringSearchEngine2(
0503:                        createSearchPattern(method, methodBinding));
0504:                engine.setFiltering(true, true);
0505:                engine.setScope(createSearchScope(method, methodBinding));
0506:                engine.setStatus(status);
0507:                engine.searchPattern(new SubProgressMonitor(pm, 1));
0508:                return (SearchResultGroup[]) engine.getResults();
0509:            }
0510:
0511:            /**
0512:             * Returns an array of <code>SearchResultGroup</code>'s containing all method
0513:             * calls in the Java project that invoke the constructor identified by the given
0514:             * <code>IMethodBinding</code>
0515:             * @param ctorBinding an <code>IMethodBinding</code> identifying a particular
0516:             * constructor signature to search for
0517:             * @param pm an <code>IProgressMonitor</code> to use during this potentially
0518:             * lengthy operation
0519:             * @param status
0520:             * @return an array of <code>SearchResultGroup</code>'s identifying all
0521:             * calls to the given constructor signature
0522:             * @throws JavaModelException 
0523:             */
0524:            private SearchResultGroup[] findAllCallsTo(
0525:                    IMethodBinding ctorBinding, IProgressMonitor pm,
0526:                    RefactoringStatus status) throws JavaModelException {
0527:                SearchResultGroup[] groups = excludeBinaryUnits(searchForCallsTo(
0528:                        ctorBinding, pm, status));
0529:
0530:                return groups;
0531:            }
0532:
0533:            private IType findNonPrimaryType(String fullyQualifiedName,
0534:                    IProgressMonitor pm, RefactoringStatus status)
0535:                    throws JavaModelException {
0536:                SearchPattern p = SearchPattern.createPattern(
0537:                        fullyQualifiedName, IJavaSearchConstants.TYPE,
0538:                        IJavaSearchConstants.DECLARATIONS,
0539:                        SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
0540:                final RefactoringSearchEngine2 engine = new RefactoringSearchEngine2(
0541:                        p);
0542:
0543:                engine.setFiltering(true, true);
0544:                engine.setScope(RefactoringScopeFactory.create(fCtorBinding
0545:                        .getJavaElement().getJavaProject()));
0546:                engine.setStatus(status);
0547:                engine.searchPattern(new SubProgressMonitor(pm, 1));
0548:
0549:                SearchResultGroup[] groups = (SearchResultGroup[]) engine
0550:                        .getResults();
0551:
0552:                if (groups.length != 0) {
0553:                    for (int i = 0; i < groups.length; i++) {
0554:                        SearchMatch[] matches = groups[i].getSearchResults();
0555:                        for (int j = 0; j < matches.length; j++) {
0556:                            if (matches[j].getAccuracy() == SearchMatch.A_ACCURATE)
0557:                                return (IType) matches[j].getElement();
0558:                        }
0559:                    }
0560:                }
0561:                return null;
0562:            }
0563:
0564:            /*
0565:             * @see org.eclipse.jdt.internal.corext.refactoring.base.Refactoring#checkInput(org.eclipse.core.runtime.IProgressMonitor)
0566:             */
0567:            public RefactoringStatus checkFinalConditions(IProgressMonitor pm)
0568:                    throws CoreException {
0569:                try {
0570:                    pm
0571:                            .beginTask(
0572:                                    RefactoringCoreMessages.IntroduceFactory_checking_preconditions,
0573:                                    1);
0574:                    RefactoringStatus result = new RefactoringStatus();
0575:
0576:                    if (fFactoryClassName != null)
0577:                        result.merge(setFactoryClass(fFactoryClassName));
0578:                    if (result.hasFatalError())
0579:                        return result;
0580:                    fArgTypes = fCtorBinding.getParameterTypes();
0581:                    fCtorIsVarArgs = fCtorBinding.isVarargs();
0582:                    fAllCallsTo = findAllCallsTo(fCtorBinding, pm, result);
0583:                    fFormalArgNames = findCtorArgNames();
0584:
0585:                    ICompilationUnit[] affectedFiles = collectAffectedUnits(fAllCallsTo);
0586:                    result.merge(Checks.validateModifiesFiles(ResourceUtil
0587:                            .getFiles(affectedFiles), getValidationContext()));
0588:
0589:                    if (fCallSitesInBinaryUnits)
0590:                        result
0591:                                .merge(RefactoringStatus
0592:                                        .createWarningStatus(RefactoringCoreMessages.IntroduceFactory_callSitesInBinaryClass));
0593:
0594:                    return result;
0595:                } finally {
0596:                    pm.done();
0597:                }
0598:            }
0599:
0600:            /**
0601:             * @return an array containing the argument names for the constructor
0602:             * identified by <code>fCtorBinding</code>, if available, or default
0603:             * names if unavailable (e.g. if the constructor resides in a binary unit).
0604:             */
0605:            private String[] findCtorArgNames() {
0606:                int numArgs = fCtorBinding.getParameterTypes().length;
0607:                String[] names = new String[numArgs];
0608:
0609:                CompilationUnit ctorUnit = (CompilationUnit) ASTNodes
0610:                        .getParent(fCtorOwningClass, CompilationUnit.class);
0611:                MethodDeclaration ctorDecl = (MethodDeclaration) ctorUnit
0612:                        .findDeclaringNode(fCtorBinding.getKey());
0613:
0614:                if (ctorDecl != null) {
0615:                    List formalArgs = ctorDecl.parameters();
0616:                    int i = 0;
0617:
0618:                    for (Iterator iter = formalArgs.iterator(); iter.hasNext(); i++) {
0619:                        SingleVariableDeclaration svd = (SingleVariableDeclaration) iter
0620:                                .next();
0621:
0622:                        names[i] = svd.getName().getIdentifier();
0623:                    }
0624:                    return names;
0625:                }
0626:
0627:                // Have no way of getting the formal argument names; just fake it.
0628:                for (int i = 0; i < numArgs; i++)
0629:                    names[i] = "arg" + (i + 1); //$NON-NLS-1$
0630:
0631:                return names;
0632:            }
0633:
0634:            /**
0635:             * Creates and returns a new MethodDeclaration that represents the factory
0636:             * method to be used in place of direct calls to the constructor in question.
0637:             * @param ast An AST used as a factory for various AST nodes
0638:             * @param ctorBinding binding for the constructor being wrapped
0639:             * @param unitRewriter the ASTRewrite to be used
0640:             * @return the new method declaration
0641:             */
0642:            private MethodDeclaration createFactoryMethod(AST ast,
0643:                    IMethodBinding ctorBinding, ASTRewrite unitRewriter) {
0644:                MethodDeclaration newMethod = ast.newMethodDeclaration();
0645:                SimpleName newMethodName = ast.newSimpleName(fNewMethodName);
0646:                ClassInstanceCreation newCtorCall = ast
0647:                        .newClassInstanceCreation();
0648:                ReturnStatement ret = ast.newReturnStatement();
0649:                Block body = ast.newBlock();
0650:                List stmts = body.statements();
0651:                String retTypeName = ctorBinding.getName();
0652:
0653:                createFactoryMethodSignature(ast, newMethod);
0654:
0655:                newMethod.setName(newMethodName);
0656:                newMethod.setBody(body);
0657:
0658:                ITypeBinding[] ctorOwnerTypeParameters = fCtorBinding
0659:                        .getDeclaringClass().getTypeParameters();
0660:
0661:                setMethodReturnType(newMethod, retTypeName,
0662:                        ctorOwnerTypeParameters, ast);
0663:
0664:                newMethod.modifiers().addAll(
0665:                        ASTNodeFactory.newModifiers(ast, Modifier.STATIC
0666:                                | Modifier.PUBLIC));
0667:
0668:                setCtorTypeArguments(newCtorCall, retTypeName,
0669:                        ctorOwnerTypeParameters, ast);
0670:
0671:                createFactoryMethodConstructorArgs(ast, newCtorCall);
0672:
0673:                ret.setExpression(newCtorCall);
0674:                stmts.add(ret);
0675:
0676:                return newMethod;
0677:            }
0678:
0679:            /**
0680:             * Sets the type being instantiated in the given constructor call, including
0681:             * specifying any necessary type arguments.
0682:             * @param newCtorCall the constructor call to modify
0683:             * @param ctorTypeName the simple name of the type being instantiated
0684:             * @param ctorOwnerTypeParameters the formal type parameters of the type being
0685:             * instantiated
0686:             * @param ast utility object used to create AST nodes
0687:             */
0688:            private void setCtorTypeArguments(
0689:                    ClassInstanceCreation newCtorCall, String ctorTypeName,
0690:                    ITypeBinding[] ctorOwnerTypeParameters, AST ast) {
0691:                if (ctorOwnerTypeParameters.length == 0) // easy, just a simple type
0692:                    newCtorCall.setType(ASTNodeFactory.newType(ast,
0693:                            ctorTypeName));
0694:                else {
0695:                    Type baseType = ast.newSimpleType(ast
0696:                            .newSimpleName(ctorTypeName));
0697:                    ParameterizedType newInstantiatedType = ast
0698:                            .newParameterizedType(baseType);
0699:                    List/*<Type>*/newInstTypeArgs = newInstantiatedType
0700:                            .typeArguments();
0701:
0702:                    for (int i = 0; i < ctorOwnerTypeParameters.length; i++) {
0703:                        Type typeArg = ASTNodeFactory.newType(ast,
0704:                                ctorOwnerTypeParameters[i].getName());
0705:
0706:                        newInstTypeArgs.add(typeArg);
0707:                    }
0708:                    newCtorCall.setType(newInstantiatedType);
0709:                }
0710:            }
0711:
0712:            /**
0713:             * Sets the return type of the factory method, including any necessary type
0714:             * arguments. E.g., for constructor <code>Foo()</code> in <code>Foo&lt;T&gt;</code>,
0715:             * the factory method defines a method type parameter <code>&lt;T&gt;</code> and
0716:             * returns a <code>Foo&lt;T&gt;</code>.
0717:             * @param newMethod the method whose return type is to be set
0718:             * @param retTypeName the simple name of the return type (without type parameters)
0719:             * @param ctorOwnerTypeParameters the formal type parameters of the type that the
0720:             * factory method instantiates (whose constructor is being encapsulated)
0721:             * @param ast utility object used to create AST nodes
0722:             */
0723:            private void setMethodReturnType(MethodDeclaration newMethod,
0724:                    String retTypeName, ITypeBinding[] ctorOwnerTypeParameters,
0725:                    AST ast) {
0726:                if (ctorOwnerTypeParameters.length == 0)
0727:                    newMethod.setReturnType2(ast.newSimpleType(ast
0728:                            .newSimpleName(retTypeName)));
0729:                else {
0730:                    Type baseType = ast.newSimpleType(ast
0731:                            .newSimpleName(retTypeName));
0732:                    ParameterizedType newRetType = ast
0733:                            .newParameterizedType(baseType);
0734:                    List/*<Type>*/newRetTypeArgs = newRetType.typeArguments();
0735:
0736:                    for (int i = 0; i < ctorOwnerTypeParameters.length; i++) {
0737:                        Type retTypeArg = ASTNodeFactory.newType(ast,
0738:                                ctorOwnerTypeParameters[i].getName());
0739:
0740:                        newRetTypeArgs.add(retTypeArg);
0741:                    }
0742:                    newMethod.setReturnType2(newRetType);
0743:                }
0744:            }
0745:
0746:            /**
0747:             * Creates and adds the necessary argument declarations to the given factory method.<br>
0748:             * An argument is needed for each original constructor argument for which the
0749:             * evaluation of the actual arguments across all calls was not able to be
0750:             * pushed inside the factory method (e.g. arguments with side-effects, references
0751:             * to fields if the factory method is to be static or reside in a factory class,
0752:             * or arguments that varied across the set of constructor calls).<br>
0753:             * <code>fArgTypes</code> identifies such arguments by a <code>null</code> value.
0754:             * @param ast utility object used to create AST nodes
0755:             * @param newMethod the <code>MethodDeclaration</code> for the factory method
0756:             */
0757:            private void createFactoryMethodSignature(AST ast,
0758:                    MethodDeclaration newMethod) {
0759:                List argDecls = newMethod.parameters();
0760:
0761:                for (int i = 0; i < fArgTypes.length; i++) {
0762:                    SingleVariableDeclaration argDecl = ast
0763:                            .newSingleVariableDeclaration();
0764:                    Type argType;
0765:
0766:                    if (i == (fArgTypes.length - 1) && fCtorIsVarArgs) {
0767:                        // The trailing varargs arg has an extra array dimension, compared to
0768:                        // what we need to pass to setType()...
0769:                        argType = typeNodeForTypeBinding(fArgTypes[i]
0770:                                .getElementType(),
0771:                                fArgTypes[i].getDimensions() - 1, ast);
0772:                        argDecl.setVarargs(true);
0773:                    } else
0774:                        argType = typeNodeForTypeBinding(fArgTypes[i], 0, ast);
0775:
0776:                    argDecl.setName(ast.newSimpleName(fFormalArgNames[i]));
0777:                    argDecl.setType(argType);
0778:                    argDecls.add(argDecl);
0779:                }
0780:
0781:                ITypeBinding[] ctorExcepts = fCtorBinding.getExceptionTypes();
0782:                List exceptions = newMethod.thrownExceptions();
0783:
0784:                for (int i = 0; i < ctorExcepts.length; i++) {
0785:                    String excName = fImportRewriter.addImport(ctorExcepts[i]);
0786:
0787:                    exceptions.add(ASTNodeFactory.newName(ast, excName));
0788:                }
0789:
0790:                copyTypeParameters(ast, newMethod);
0791:            }
0792:
0793:            /**
0794:             * Copies the constructor's parent type's type parameters, if any, as
0795:             * method type parameters of the new static factory method. (Recall
0796:             * that static methods can't refer to type arguments of the enclosing
0797:             * class, since they have no instance to serve as a context.)<br>
0798:             * Makes sure to copy the bounds from the owning type, to ensure that the
0799:             * return type of the factory method satisfies the bounds of the type
0800:             * being instantiated.<br>
0801:             * E.g., for ctor Foo() in the type Foo<T extends Number>, be sure that
0802:             * the factory method is declared as<br>
0803:             * <code>static <T extends Number> Foo<T> createFoo()</code><br>
0804:             * and not simply<br>
0805:             * <code>static <T> Foo<T> createFoo()</code><br>
0806:             * or the compiler will bark.
0807:             * @param ast utility object needed to create ASTNode's for the new method
0808:             * @param newMethod the method onto which to copy the type parameters
0809:             */
0810:            private void copyTypeParameters(AST ast, MethodDeclaration newMethod) {
0811:                ITypeBinding[] ctorOwnerTypeParms = fCtorBinding
0812:                        .getDeclaringClass().getTypeParameters();
0813:                List/*<TypeParameter>*/factoryMethodTypeParms = newMethod
0814:                        .typeParameters();
0815:                for (int i = 0; i < ctorOwnerTypeParms.length; i++) {
0816:                    TypeParameter newParm = ast.newTypeParameter();
0817:                    ITypeBinding[] parmTypeBounds = ctorOwnerTypeParms[i]
0818:                            .getTypeBounds();
0819:                    List/*<Type>*/newParmBounds = newParm.typeBounds();
0820:
0821:                    newParm.setName(ast.newSimpleName(ctorOwnerTypeParms[i]
0822:                            .getName()));
0823:                    for (int b = 0; b < parmTypeBounds.length; b++) {
0824:                        if (parmTypeBounds[b].isClass()
0825:                                && parmTypeBounds[b].getSuperclass() == null)
0826:                            continue;
0827:
0828:                        Type newBound = fImportRewriter.addImport(
0829:                                parmTypeBounds[b], ast);
0830:
0831:                        newParmBounds.add(newBound);
0832:                    }
0833:                    factoryMethodTypeParms.add(newParm);
0834:                }
0835:            }
0836:
0837:            /**
0838:             * @param argType 
0839:             * @param extraDims number of extra array dimensions to add to the resulting type
0840:             * @param ast 
0841:             * @return a Type that describes the given ITypeBinding. If the binding
0842:             * refers to an object type, use the import rewriter to determine whether
0843:             * the reference requires a new import, or instead needs to be qualified.<br>
0844:             * Like ASTNodeFactory.newType(), but for the handling of imports.
0845:             */
0846:            private Type typeNodeForTypeBinding(ITypeBinding argType,
0847:                    int extraDims, AST ast) {
0848:                if (extraDims > 0) {
0849:                    return ast.newArrayType(typeNodeForTypeBinding(argType, 0,
0850:                            ast), extraDims);
0851:
0852:                } else if (argType.isArray()) {
0853:                    Type elementType = typeNodeForTypeBinding(argType
0854:                            .getElementType(), extraDims, ast);
0855:                    return ast.newArrayType(elementType, argType
0856:                            .getDimensions());
0857:
0858:                } else {
0859:                    return fImportRewriter.addImport(argType, ast);
0860:                }
0861:            }
0862:
0863:            /**
0864:             * Create the list of actual arguments to the constructor call that is
0865:             * encapsulated inside the factory method, and associate the arguments
0866:             * with the given constructor call object.
0867:             * @param ast utility object used to create AST nodes
0868:             * @param newCtorCall the newly-generated constructor call to be wrapped inside
0869:             * the factory method
0870:             */
0871:            private void createFactoryMethodConstructorArgs(AST ast,
0872:                    ClassInstanceCreation newCtorCall) {
0873:                List argList = newCtorCall.arguments();
0874:
0875:                for (int i = 0; i < fArgTypes.length; i++) {
0876:                    ASTNode ctorArg = ast.newSimpleName(fFormalArgNames[i]);
0877:
0878:                    argList.add(ctorArg);
0879:                }
0880:            }
0881:
0882:            /**
0883:             * Updates the constructor call.
0884:             * 
0885:             * @param ctorCall the ClassInstanceCreation to be marked as replaced
0886:             * @param unitRewriter the AST rewriter
0887:             * @param gd the edit group to use
0888:             */
0889:            private void rewriteFactoryMethodCall(
0890:                    ClassInstanceCreation ctorCall, ASTRewrite unitRewriter,
0891:                    TextEditGroup gd) {
0892:                AST ast = unitRewriter.getAST();
0893:                MethodInvocation factoryMethodCall = ast.newMethodInvocation();
0894:
0895:                List actualFactoryArgs = factoryMethodCall.arguments();
0896:                List actualCtorArgs = ctorCall.arguments();
0897:
0898:                // Need to use a qualified name for the factory method if we're not
0899:                // in the context of the class holding the factory.
0900:                AbstractTypeDeclaration callOwner = (AbstractTypeDeclaration) ASTNodes
0901:                        .getParent(ctorCall, AbstractTypeDeclaration.class);
0902:                ITypeBinding callOwnerBinding = callOwner.resolveBinding();
0903:
0904:                if (callOwnerBinding == null
0905:                        || !Bindings.equals(callOwner.resolveBinding(),
0906:                                fFactoryOwningClass.resolveBinding())) {
0907:                    String qualifier = fImportRewriter
0908:                            .addImport(fFactoryOwningClass.resolveBinding());
0909:                    factoryMethodCall.setExpression(ASTNodeFactory.newName(ast,
0910:                            qualifier));
0911:                }
0912:
0913:                factoryMethodCall.setName(ast.newSimpleName(fNewMethodName));
0914:
0915:                for (int i = 0; i < actualCtorArgs.size(); i++) {
0916:                    Expression actualCtorArg = (Expression) actualCtorArgs
0917:                            .get(i);
0918:                    ASTNode movedArg = unitRewriter
0919:                            .createMoveTarget(actualCtorArg);
0920:                    actualFactoryArgs.add(movedArg);
0921:                }
0922:
0923:                unitRewriter.replace(ctorCall, factoryMethodCall, gd);
0924:            }
0925:
0926:            /**
0927:             * @param unit
0928:             * @return true iff the given <code>ICompilationUnit</code> is the unit
0929:             * containing the original constructor
0930:             */
0931:            private boolean isConstructorUnit(ICompilationUnit unit) {
0932:                return unit.equals(ASTCreator.getCu(fCtorOwningClass));
0933:            }
0934:
0935:            /**
0936:             * @return true iff we should actually change the original constructor's
0937:             * visibility to <code>protected</code>. This takes into account the user-
0938:             * requested mode and whether the constructor's compilation unit is in
0939:             * source form.
0940:             */
0941:            private boolean shouldProtectConstructor() {
0942:                return fProtectConstructor && fCtorOwningClass != null;
0943:            }
0944:
0945:            /**
0946:             * Creates and adds the necessary change to make the constructor method protected.
0947:             * @param unitAST 
0948:             * @param unitRewriter 
0949:             * @param declGD 
0950:             * @return false iff the constructor didn't exist (i.e. was implicit)
0951:             */
0952:            private boolean protectConstructor(CompilationUnit unitAST,
0953:                    ASTRewrite unitRewriter, TextEditGroup declGD) {
0954:                MethodDeclaration constructor = (MethodDeclaration) unitAST
0955:                        .findDeclaringNode(fCtorBinding.getKey());
0956:
0957:                // No need to rewrite the modifiers if the visibility is what we already want it to be.
0958:                if (constructor == null
0959:                        || (JdtFlags.getVisibilityCode(constructor)) == fConstructorVisibility)
0960:                    return false;
0961:                ModifierRewrite.create(unitRewriter, constructor)
0962:                        .setVisibility(fConstructorVisibility, declGD);
0963:                return true;
0964:            }
0965:
0966:            /**
0967:             * Add all changes necessary on the <code>ICompilationUnit</code> in the given
0968:             * <code>SearchResultGroup</code> to implement the refactoring transformation
0969:             * to the given <code>CompilationUnitChange</code>.
0970:             * @param rg the <code>SearchResultGroup</code> for which changes should be created
0971:             * @param unitHandle 
0972:             * @param unitChange the CompilationUnitChange object for the compilation unit in question
0973:             * @return <code>true</code> iff a change has been added
0974:             * @throws CoreException
0975:             */
0976:            private boolean addAllChangesFor(SearchResultGroup rg,
0977:                    ICompilationUnit unitHandle,
0978:                    CompilationUnitChange unitChange) throws CoreException {
0979:                //		ICompilationUnit	unitHandle= rg.getCompilationUnit();
0980:                Assert.isTrue(rg == null
0981:                        || rg.getCompilationUnit() == unitHandle);
0982:                CompilationUnit unit = getASTFor(unitHandle);
0983:                ASTRewrite unitRewriter = ASTRewrite.create(unit.getAST());
0984:                MultiTextEdit root = new MultiTextEdit();
0985:                boolean someChange = false;
0986:
0987:                unitChange.setEdit(root);
0988:                fImportRewriter = StubUtility.createImportRewrite(unit, true);
0989:
0990:                // First create the factory method
0991:                if (unitHandle.equals(fFactoryUnitHandle)) {
0992:                    TextEditGroup factoryGD = new TextEditGroup(
0993:                            RefactoringCoreMessages.IntroduceFactory_addFactoryMethod);
0994:
0995:                    createFactoryChange(unitRewriter, unit, factoryGD);
0996:                    unitChange.addTextEditGroup(factoryGD);
0997:                    someChange = true;
0998:                }
0999:
1000:                // Now rewrite all the constructor calls to use the factory method
1001:                if (rg != null)
1002:                    if (replaceConstructorCalls(rg, unit, unitRewriter,
1003:                            unitChange))
1004:                        someChange = true;
1005:
1006:                // Finally, make the constructor private, if requested.
1007:                if (shouldProtectConstructor() && isConstructorUnit(unitHandle)) {
1008:                    TextEditGroup declGD = new TextEditGroup(
1009:                            RefactoringCoreMessages.IntroduceFactory_protectConstructor);
1010:
1011:                    if (protectConstructor(unit, unitRewriter, declGD)) {
1012:                        unitChange.addTextEditGroup(declGD);
1013:                        someChange = true;
1014:                    }
1015:                }
1016:
1017:                if (someChange) {
1018:                    root.addChild(unitRewriter.rewriteAST());
1019:                    root.addChild(fImportRewriter.rewriteImports(null));
1020:                }
1021:
1022:                return someChange;
1023:            }
1024:
1025:            /**
1026:             * @param unitHandle 
1027:             * @return an AST for the given compilation unit handle.<br>
1028:             * If this is the unit containing the selection or the unit in which the factory
1029:             * is to reside, checks the appropriate field (<code>fCU</code> or <code>fFactoryCU</code>,
1030:             * respectively) and initializes the field with a new AST only if not already done.
1031:             */
1032:            private CompilationUnit getASTFor(ICompilationUnit unitHandle) {
1033:                if (unitHandle.equals(fCUHandle)) { // is this the unit containing the selection?
1034:                    if (fCU == null) {
1035:                        fCU = ASTCreator.createAST(unitHandle, null);
1036:                        if (fCU.equals(fFactoryUnitHandle)) // if selection unit and factory unit are the same...
1037:                            fFactoryCU = fCU; // ...make sure the factory unit gets initialized
1038:                    }
1039:                    return fCU;
1040:                } else if (unitHandle.equals(fFactoryUnitHandle)) { // is this the "factory unit"?
1041:                    if (fFactoryCU == null)
1042:                        fFactoryCU = ASTCreator.createAST(unitHandle, null);
1043:                    return fFactoryCU;
1044:                } else
1045:                    return ASTCreator.createAST(unitHandle, null);
1046:            }
1047:
1048:            /**
1049:             * Use the given <code>ASTRewrite</code> to replace direct calls to the constructor
1050:             * with calls to the newly-created factory method.
1051:             * @param rg the <code>SearchResultGroup</code> indicating all of the constructor references
1052:             * @param unit the <code>CompilationUnit</code> to be rewritten
1053:             * @param unitRewriter the rewriter
1054:             * @param unitChange the compilation unit change
1055:             * @throws CoreException
1056:             * @return true iff at least one constructor call site was rewritten.
1057:             */
1058:            private boolean replaceConstructorCalls(SearchResultGroup rg,
1059:                    CompilationUnit unit, ASTRewrite unitRewriter,
1060:                    CompilationUnitChange unitChange) throws CoreException {
1061:                Assert.isTrue(ASTCreator.getCu(unit).equals(
1062:                        rg.getCompilationUnit()));
1063:                SearchMatch[] hits = rg.getSearchResults();
1064:                boolean someCallPatched = false;
1065:
1066:                for (int i = 0; i < hits.length; i++) {
1067:                    ASTNode ctrCall = getCtorCallAt(hits[i].getOffset(),
1068:                            hits[i].getLength(), unit);
1069:
1070:                    if (ctrCall instanceof  ClassInstanceCreation) {
1071:                        TextEditGroup gd = new TextEditGroup(
1072:                                RefactoringCoreMessages.IntroduceFactory_replaceCalls);
1073:
1074:                        rewriteFactoryMethodCall(
1075:                                (ClassInstanceCreation) ctrCall, unitRewriter,
1076:                                gd);
1077:                        unitChange.addTextEditGroup(gd);
1078:                        someCallPatched = true;
1079:                    } else if (ctrCall instanceof  MethodRef) {
1080:                        TextEditGroup gd = new TextEditGroup(
1081:                                RefactoringCoreMessages.IntroduceFactoryRefactoring_replaceJavadocReference);
1082:
1083:                        rewriteJavadocReference((MethodRef) ctrCall,
1084:                                unitRewriter, gd);
1085:                        unitChange.addTextEditGroup(gd);
1086:                        someCallPatched = true;
1087:                    }
1088:                }
1089:                return someCallPatched;
1090:            }
1091:
1092:            private void rewriteJavadocReference(MethodRef javadocRef,
1093:                    ASTRewrite unitRewriter, TextEditGroup gd) {
1094:                AST ast = unitRewriter.getAST();
1095:                unitRewriter.replace(javadocRef.getName(), ast
1096:                        .newSimpleName(fNewMethodName), gd);
1097:            }
1098:
1099:            /**
1100:             * Look "in the vicinity" of the given range to find the <code>ClassInstanceCreation</code>
1101:             * node that this search hit identified. Necessary because the <code>SearchEngine</code>
1102:             * doesn't always cough up text extents that <code>NodeFinder.perform()</code> agrees with.
1103:             * @param start
1104:             * @param length
1105:             * @param unitAST
1106:             * @return return a {@link ClassInstanceCreation} or a {@link MethodRef} or <code>null</code> if this is really a constructor->constructor call (e.g. "this(...)")
1107:             * @throws CoreException 
1108:             */
1109:            private ASTNode getCtorCallAt(int start, int length,
1110:                    CompilationUnit unitAST) throws CoreException {
1111:                ICompilationUnit unitHandle = ASTCreator.getCu(unitAST);
1112:                ASTNode node = NodeFinder.perform(unitAST, start, length);
1113:
1114:                if (node == null)
1115:                    throw new CoreException(
1116:                            JavaUIStatus
1117:                                    .createError(
1118:                                            IStatus.ERROR,
1119:                                            Messages
1120:                                                    .format(
1121:                                                            RefactoringCoreMessages.IntroduceFactory_noASTNodeForConstructorSearchHit,
1122:                                                            new Object[] {
1123:                                                                    Integer
1124:                                                                            .toString(start),
1125:                                                                    Integer
1126:                                                                            .toString(start
1127:                                                                                    + length),
1128:                                                                    unitHandle
1129:                                                                            .getSource()
1130:                                                                            .substring(
1131:                                                                                    start,
1132:                                                                                    start
1133:                                                                                            + length),
1134:                                                                    unitHandle
1135:                                                                            .getElementName() }),
1136:                                            null));
1137:
1138:                if (node instanceof  ClassInstanceCreation) {
1139:                    return node;
1140:                } else if (node instanceof  VariableDeclaration) {
1141:                    Expression init = ((VariableDeclaration) node)
1142:                            .getInitializer();
1143:
1144:                    if (init instanceof  ClassInstanceCreation) {
1145:                        return init;
1146:                    } else if (init != null)
1147:                        throw new CoreException(
1148:                                JavaUIStatus
1149:                                        .createError(
1150:                                                IStatus.ERROR,
1151:                                                Messages
1152:                                                        .format(
1153:                                                                RefactoringCoreMessages.IntroduceFactory_unexpectedInitializerNodeType,
1154:                                                                new Object[] {
1155:                                                                        init
1156:                                                                                .toString(),
1157:                                                                        unitHandle
1158:                                                                                .getElementName() }),
1159:                                                null));
1160:                    else
1161:                        throw new CoreException(
1162:                                JavaUIStatus
1163:                                        .createError(
1164:                                                IStatus.ERROR,
1165:                                                Messages
1166:                                                        .format(
1167:                                                                RefactoringCoreMessages.IntroduceFactory_noConstructorCallNodeInsideFoundVarbleDecl,
1168:                                                                new Object[] { node
1169:                                                                        .toString() }),
1170:                                                null));
1171:                } else if (node instanceof  ConstructorInvocation) {
1172:                    // This is a call we can bypass; it's from one constructor flavor
1173:                    // to another flavor on the same class.
1174:                    return null;
1175:                } else if (node instanceof  SuperConstructorInvocation) {
1176:                    // This is a call we can bypass; it's from one constructor flavor
1177:                    // to another flavor on the same class.
1178:                    fConstructorVisibility = Modifier.PROTECTED;
1179:                    return null;
1180:                } else if (node instanceof  ExpressionStatement) {
1181:                    Expression expr = ((ExpressionStatement) node)
1182:                            .getExpression();
1183:
1184:                    if (expr instanceof  ClassInstanceCreation)
1185:                        return expr;
1186:                    else
1187:                        throw new CoreException(
1188:                                JavaUIStatus
1189:                                        .createError(
1190:                                                IStatus.ERROR,
1191:                                                Messages
1192:                                                        .format(
1193:                                                                RefactoringCoreMessages.IntroduceFactory_unexpectedASTNodeTypeForConstructorSearchHit,
1194:                                                                new Object[] {
1195:                                                                        expr
1196:                                                                                .toString(),
1197:                                                                        unitHandle
1198:                                                                                .getElementName() }),
1199:                                                null));
1200:                } else if (node instanceof  SimpleName
1201:                        && (node.getParent() instanceof  MethodDeclaration || node
1202:                                .getParent() instanceof  AbstractTypeDeclaration)) {
1203:                    // We seem to have been given a hit for an implicit call to the base-class constructor.
1204:                    // Do nothing with this (implicit) call, but have to make sure we make the derived class
1205:                    // doesn't lose access to the base-class constructor (so make it 'protected', not 'private').
1206:                    fConstructorVisibility = Modifier.PROTECTED;
1207:                    return null;
1208:                } else if (node instanceof  MethodRef) {
1209:                    return node;
1210:                } else
1211:                    throw new CoreException(
1212:                            JavaUIStatus
1213:                                    .createError(
1214:                                            IStatus.ERROR,
1215:                                            Messages
1216:                                                    .format(
1217:                                                            RefactoringCoreMessages.IntroduceFactory_unexpectedASTNodeTypeForConstructorSearchHit,
1218:                                                            new Object[] {
1219:                                                                    node
1220:                                                                            .getClass()
1221:                                                                            .getName()
1222:                                                                            + "('" + node.toString() + "')", unitHandle.getElementName() }), //$NON-NLS-1$ //$NON-NLS-2$
1223:                                            null));
1224:            }
1225:
1226:            /**
1227:             * Perform the AST rewriting necessary on the given <code>CompilationUnit</code>
1228:             * to create the factory method. The method will reside on the type identified by
1229:             * <code>fFactoryOwningClass</code>.
1230:             * @param unitRewriter
1231:             * @param unit
1232:             * @param gd the <code>GroupDescription</code> to associate with the changes made
1233:             */
1234:            private void createFactoryChange(ASTRewrite unitRewriter,
1235:                    CompilationUnit unit, TextEditGroup gd) {
1236:                // ================================================================================
1237:                // First add the factory itself (method, class, and interface as needed/directed by user)
1238:                AST ast = unit.getAST();
1239:
1240:                fFactoryMethod = createFactoryMethod(ast, fCtorBinding,
1241:                        unitRewriter);
1242:
1243:                AbstractTypeDeclaration factoryOwner = (AbstractTypeDeclaration) unit
1244:                        .findDeclaringNode(fFactoryOwningClass.resolveBinding()
1245:                                .getKey());
1246:                fImportRewriter.addImport(fCtorOwningClass.resolveBinding());
1247:
1248:                int idx = ASTNodes.getInsertionIndex(fFactoryMethod,
1249:                        factoryOwner.bodyDeclarations());
1250:
1251:                if (idx < 0)
1252:                    idx = 0; // Guard against bug in getInsertionIndex()
1253:                unitRewriter.getListRewrite(factoryOwner,
1254:                        factoryOwner.getBodyDeclarationsProperty()).insertAt(
1255:                        fFactoryMethod, idx, gd);
1256:            }
1257:
1258:            /* (non-Javadoc)
1259:             * @see org.eclipse.ltk.core.refactoring.Refactoring#createChange(org.eclipse.core.runtime.IProgressMonitor)
1260:             */
1261:            public Change createChange(IProgressMonitor pm)
1262:                    throws CoreException {
1263:                try {
1264:                    pm
1265:                            .beginTask(
1266:                                    RefactoringCoreMessages.IntroduceFactory_createChanges,
1267:                                    fAllCallsTo.length);
1268:                    final ITypeBinding binding = fFactoryOwningClass
1269:                            .resolveBinding();
1270:                    final Map arguments = new HashMap();
1271:                    String project = null;
1272:                    IJavaProject javaProject = fCUHandle.getJavaProject();
1273:                    if (javaProject != null)
1274:                        project = javaProject.getElementName();
1275:                    int flags = JavaRefactoringDescriptor.JAR_MIGRATION
1276:                            | JavaRefactoringDescriptor.JAR_REFACTORING
1277:                            | RefactoringDescriptor.STRUCTURAL_CHANGE
1278:                            | RefactoringDescriptor.MULTI_CHANGE;
1279:                    if (binding.isNested() && !binding.isMember())
1280:                        flags |= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
1281:                    final String description = Messages
1282:                            .format(
1283:                                    RefactoringCoreMessages.IntroduceFactoryRefactoring_descriptor_description_short,
1284:                                    fCtorOwningClass.getName());
1285:                    final String header = Messages
1286:                            .format(
1287:                                    RefactoringCoreMessages.IntroduceFactory_descriptor_description,
1288:                                    new String[] {
1289:                                            fNewMethodName,
1290:                                            BindingLabelProvider
1291:                                                    .getBindingLabel(
1292:                                                            binding,
1293:                                                            JavaElementLabels.ALL_FULLY_QUALIFIED),
1294:                                            BindingLabelProvider
1295:                                                    .getBindingLabel(
1296:                                                            fCtorBinding,
1297:                                                            JavaElementLabels.ALL_FULLY_QUALIFIED) });
1298:                    final JDTRefactoringDescriptorComment comment = new JDTRefactoringDescriptorComment(
1299:                            project, this , header);
1300:                    comment
1301:                            .addSetting(Messages
1302:                                    .format(
1303:                                            RefactoringCoreMessages.IntroduceFactoryRefactoring_original_pattern,
1304:                                            BindingLabelProvider
1305:                                                    .getBindingLabel(
1306:                                                            fCtorBinding,
1307:                                                            JavaElementLabels.ALL_FULLY_QUALIFIED)));
1308:                    comment
1309:                            .addSetting(Messages
1310:                                    .format(
1311:                                            RefactoringCoreMessages.IntroduceFactoryRefactoring_factory_pattern,
1312:                                            fNewMethodName));
1313:                    comment
1314:                            .addSetting(Messages
1315:                                    .format(
1316:                                            RefactoringCoreMessages.IntroduceFactoryRefactoring_owner_pattern,
1317:                                            BindingLabelProvider
1318:                                                    .getBindingLabel(
1319:                                                            binding,
1320:                                                            JavaElementLabels.ALL_FULLY_QUALIFIED)));
1321:                    if (fProtectConstructor)
1322:                        comment
1323:                                .addSetting(RefactoringCoreMessages.IntroduceFactoryRefactoring_declare_private);
1324:                    final IntroduceFactoryDescriptor descriptor = new IntroduceFactoryDescriptor(
1325:                            project, description, comment.asString(),
1326:                            arguments, flags);
1327:                    arguments.put(
1328:                            JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT,
1329:                            JavaRefactoringDescriptorUtil.elementToHandle(
1330:                                    project, fCUHandle));
1331:                    arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME,
1332:                            fNewMethodName);
1333:                    arguments
1334:                            .put(
1335:                                    JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + 1,
1336:                                    JavaRefactoringDescriptorUtil
1337:                                            .elementToHandle(project, binding
1338:                                                    .getJavaElement()));
1339:                    arguments
1340:                            .put(
1341:                                    JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION,
1342:                                    new Integer(fSelectionStart).toString()
1343:                                            + " " + new Integer(fSelectionLength).toString()); //$NON-NLS-1$
1344:                    arguments.put(ATTRIBUTE_PROTECT, Boolean.valueOf(
1345:                            fProtectConstructor).toString());
1346:                    final DynamicValidationStateChange result = new DynamicValidationRefactoringChange(
1347:                            descriptor,
1348:                            RefactoringCoreMessages.IntroduceFactory_name);
1349:                    boolean hitInFactoryClass = false;
1350:                    boolean hitInCtorClass = false;
1351:                    for (int i = 0; i < fAllCallsTo.length; i++) {
1352:                        SearchResultGroup rg = fAllCallsTo[i];
1353:                        ICompilationUnit unitHandle = rg.getCompilationUnit();
1354:                        CompilationUnitChange cuChange = new CompilationUnitChange(
1355:                                getName(), unitHandle);
1356:
1357:                        if (addAllChangesFor(rg, unitHandle, cuChange))
1358:                            result.add(cuChange);
1359:
1360:                        if (unitHandle.equals(fFactoryUnitHandle))
1361:                            hitInFactoryClass = true;
1362:                        if (unitHandle.equals(ASTCreator
1363:                                .getCu(fCtorOwningClass)))
1364:                            hitInCtorClass = true;
1365:
1366:                        pm.worked(1);
1367:                        if (pm.isCanceled())
1368:                            throw new OperationCanceledException();
1369:                    }
1370:                    if (!hitInFactoryClass) { // Handle factory class if no search hits there
1371:                        CompilationUnitChange cuChange = new CompilationUnitChange(
1372:                                getName(), fFactoryUnitHandle);
1373:                        addAllChangesFor(null, fFactoryUnitHandle, cuChange);
1374:                        result.add(cuChange);
1375:                    }
1376:                    if (!hitInCtorClass
1377:                            && !fFactoryUnitHandle.equals(ASTCreator
1378:                                    .getCu(fCtorOwningClass))) { // Handle constructor-owning class if no search hits there
1379:                        CompilationUnitChange cuChange = new CompilationUnitChange(
1380:                                getName(), ASTCreator.getCu(fCtorOwningClass));
1381:                        addAllChangesFor(null, ASTCreator
1382:                                .getCu(fCtorOwningClass), cuChange);
1383:                        result.add(cuChange);
1384:                    }
1385:                    return result;
1386:                } finally {
1387:                    pm.done();
1388:                }
1389:            }
1390:
1391:            /* (non-Javadoc)
1392:             * @see org.eclipse.ltk.core.refactoring.Refactoring#getName()
1393:             */
1394:            public String getName() {
1395:                return RefactoringCoreMessages.IntroduceFactory_name;
1396:            }
1397:
1398:            /**
1399:             * Returns the name to be used for the generated factory method.
1400:             * @return the new method name
1401:             */
1402:            public String getNewMethodName() {
1403:                return fNewMethodName;
1404:            }
1405:
1406:            /**
1407:             * Sets the name to be used for the generated factory method.<br>
1408:             * Returns a <code>RefactoringStatus</code> that indicates whether the
1409:             * given name is valid for the new factory method.
1410:             * @param newMethodName the name to be used for the generated factory method
1411:             * @return the resulting status
1412:             */
1413:            public RefactoringStatus setNewMethodName(String newMethodName) {
1414:                Assert.isNotNull(newMethodName);
1415:                fNewMethodName = newMethodName;
1416:
1417:                RefactoringStatus stat = Checks.checkMethodName(newMethodName,
1418:                        fCUHandle);
1419:
1420:                stat.merge(isUniqueMethodName(newMethodName));
1421:
1422:                return stat;
1423:            }
1424:
1425:            /**
1426:             * @param methodName
1427:             * @return a <code>RefactoringStatus</code> that identifies whether the
1428:             * the name <code>newMethodName</code> is available to use as the name of
1429:             * the new factory method within the factory-owner class (either a to-be-
1430:             * created factory class or the constructor-owning class, depending on the
1431:             * user options).
1432:             */
1433:            private RefactoringStatus isUniqueMethodName(String methodName) {
1434:                ITypeBinding declaringClass = fCtorBinding.getDeclaringClass();
1435:                if (Bindings.findMethodInType(declaringClass, methodName,
1436:                        fCtorBinding.getParameterTypes()) != null) {
1437:                    String format = Messages
1438:                            .format(
1439:                                    RefactoringCoreMessages.IntroduceFactory_duplicateMethodName,
1440:                                    methodName);
1441:                    return RefactoringStatus.createErrorStatus(format);
1442:                }
1443:                return new RefactoringStatus();
1444:            }
1445:
1446:            /**
1447:             * Returns true iff the selected constructor can be protected.
1448:             * @return return <code>true</code> if the constructor can be made protected
1449:             */
1450:            public boolean canProtectConstructor() {
1451:                return !fCtorBinding.isSynthetic()
1452:                        && fFactoryCU.findDeclaringNode(fCtorBinding.getKey()) != null;
1453:            }
1454:
1455:            /**
1456:             * If the argument is true, change the visibility of the constructor to
1457:             * <code>protected</code>, thereby encapsulating it.
1458:             * @param protectConstructor
1459:             */
1460:            public void setProtectConstructor(boolean protectConstructor) {
1461:                fProtectConstructor = protectConstructor;
1462:            }
1463:
1464:            /**
1465:             * Returns the project on behalf of which this refactoring was invoked.
1466:             * @return returns the Java project
1467:             */
1468:            public IJavaProject getProject() {
1469:                return fCUHandle.getJavaProject();
1470:            }
1471:
1472:            /**
1473:             * Sets the class on which the generated factory method is to be placed.
1474:             * @param fullyQualifiedTypeName an <code>IType</code> referring to an existing class
1475:             * @return return the resulting status
1476:             */
1477:            public RefactoringStatus setFactoryClass(
1478:                    String fullyQualifiedTypeName) {
1479:                IType factoryType;
1480:
1481:                try {
1482:                    factoryType = findFactoryClass(fullyQualifiedTypeName);
1483:                    if (factoryType == null)
1484:                        return RefactoringStatus
1485:                                .createErrorStatus(Messages
1486:                                        .format(
1487:                                                RefactoringCoreMessages.IntroduceFactory_noSuchClass,
1488:                                                fullyQualifiedTypeName));
1489:
1490:                    if (factoryType.isAnnotation())
1491:                        return RefactoringStatus
1492:                                .createErrorStatus(RefactoringCoreMessages.IntroduceFactory_cantPutFactoryMethodOnAnnotation);
1493:                    if (factoryType.isInterface())
1494:                        return RefactoringStatus
1495:                                .createErrorStatus(RefactoringCoreMessages.IntroduceFactory_cantPutFactoryMethodOnInterface);
1496:                } catch (JavaModelException e) {
1497:                    return RefactoringStatus
1498:                            .createFatalErrorStatus(RefactoringCoreMessages.IntroduceFactory_cantCheckForInterface);
1499:                }
1500:
1501:                ICompilationUnit factoryUnitHandle = factoryType
1502:                        .getCompilationUnit();
1503:
1504:                if (factoryType.isBinary())
1505:                    return RefactoringStatus
1506:                            .createErrorStatus(RefactoringCoreMessages.IntroduceFactory_cantPutFactoryInBinaryClass);
1507:                else {
1508:                    try {
1509:                        if (!fFactoryUnitHandle.equals(factoryUnitHandle)) {
1510:                            fFactoryCU = getASTFor(factoryUnitHandle);
1511:                            fFactoryUnitHandle = factoryUnitHandle;
1512:                        }
1513:                        fFactoryOwningClass = (AbstractTypeDeclaration) ASTNodes
1514:                                .getParent(NodeFinder.perform(fFactoryCU,
1515:                                        factoryType.getNameRange()),
1516:                                        AbstractTypeDeclaration.class);
1517:
1518:                        String factoryPkg = factoryType.getPackageFragment()
1519:                                .getElementName();
1520:                        String ctorPkg = fCtorOwningClass.resolveBinding()
1521:                                .getPackage().getName();
1522:
1523:                        if (!factoryPkg.equals(ctorPkg))
1524:                            fConstructorVisibility = Modifier.PUBLIC;
1525:                        else if (fFactoryOwningClass != fCtorOwningClass)
1526:                            fConstructorVisibility = 0; // No such thing as Modifier.PACKAGE...
1527:
1528:                        if (fFactoryOwningClass != fCtorOwningClass)
1529:                            fConstructorVisibility = 0; // No such thing as Modifier.PACKAGE...
1530:
1531:                    } catch (JavaModelException e) {
1532:                        return RefactoringStatus.createFatalErrorStatus(e
1533:                                .getMessage());
1534:                    }
1535:                    return new RefactoringStatus();
1536:                }
1537:            }
1538:
1539:            /**
1540:             * Finds the factory class associated with the fully qualified name.
1541:             * @param fullyQualifiedTypeName the fully qualified type name
1542:             * @return the factory class, or <code>null</code> if not found
1543:             * @throws JavaModelException if an error occurs while finding the factory class
1544:             */
1545:            private IType findFactoryClass(String fullyQualifiedTypeName)
1546:                    throws JavaModelException {
1547:                IType factoryType = getProject().findType(
1548:                        fullyQualifiedTypeName);
1549:                if (factoryType == null) // presumably a non-primary type; try the search engine
1550:                    factoryType = findNonPrimaryType(fullyQualifiedTypeName,
1551:                            new NullProgressMonitor(), new RefactoringStatus());
1552:                return factoryType;
1553:            }
1554:
1555:            /**
1556:             * Returns the name of the class on which the generated factory method is
1557:             * to be placed.
1558:             * @return return the factory class name
1559:             */
1560:            public String getFactoryClassName() {
1561:                return fFactoryOwningClass.resolveBinding().getQualifiedName();
1562:            }
1563:
1564:            public RefactoringStatus initialize(
1565:                    final RefactoringArguments arguments) {
1566:                if (arguments instanceof  JavaRefactoringArguments) {
1567:                    final JavaRefactoringArguments extended = (JavaRefactoringArguments) arguments;
1568:                    final String selection = extended
1569:                            .getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION);
1570:                    if (selection != null) {
1571:                        int offset = -1;
1572:                        int length = -1;
1573:                        final StringTokenizer tokenizer = new StringTokenizer(
1574:                                selection);
1575:                        if (tokenizer.hasMoreTokens())
1576:                            offset = Integer.valueOf(tokenizer.nextToken())
1577:                                    .intValue();
1578:                        if (tokenizer.hasMoreTokens())
1579:                            length = Integer.valueOf(tokenizer.nextToken())
1580:                                    .intValue();
1581:                        if (offset >= 0 && length >= 0) {
1582:                            fSelectionStart = offset;
1583:                            fSelectionLength = length;
1584:                        } else
1585:                            return RefactoringStatus
1586:                                    .createFatalErrorStatus(Messages
1587:                                            .format(
1588:                                                    RefactoringCoreMessages.InitializableRefactoring_illegal_argument,
1589:                                                    new Object[] {
1590:                                                            selection,
1591:                                                            JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION }));
1592:                    } else
1593:                        return RefactoringStatus
1594:                                .createFatalErrorStatus(Messages
1595:                                        .format(
1596:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1597:                                                JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION));
1598:                    String handle = extended
1599:                            .getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
1600:                    if (handle != null) {
1601:                        final IJavaElement element = JavaRefactoringDescriptorUtil
1602:                                .handleToElement(extended.getProject(), handle,
1603:                                        false);
1604:                        if (element == null
1605:                                || !element.exists()
1606:                                || element.getElementType() != IJavaElement.COMPILATION_UNIT)
1607:                            return createInputFatalStatus(element,
1608:                                    IJavaRefactorings.INTRODUCE_FACTORY);
1609:                        else {
1610:                            fCUHandle = (ICompilationUnit) element;
1611:                            initialize();
1612:                        }
1613:                    } else
1614:                        return RefactoringStatus
1615:                                .createFatalErrorStatus(Messages
1616:                                        .format(
1617:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1618:                                                JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
1619:                    handle = extended
1620:                            .getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + 1);
1621:                    if (handle != null) {
1622:                        final IJavaElement element = JavaRefactoringDescriptorUtil
1623:                                .handleToElement(extended.getProject(), handle,
1624:                                        false);
1625:                        if (element == null
1626:                                || !element.exists()
1627:                                || element.getElementType() != IJavaElement.TYPE)
1628:                            return createInputFatalStatus(element,
1629:                                    IJavaRefactorings.INTRODUCE_FACTORY);
1630:                        else {
1631:                            final IType type = (IType) element;
1632:                            fFactoryClassName = type.getFullyQualifiedName();
1633:                        }
1634:                    } else
1635:                        return RefactoringStatus
1636:                                .createFatalErrorStatus(Messages
1637:                                        .format(
1638:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1639:                                                JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
1640:                    final String name = extended
1641:                            .getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME);
1642:                    if (name != null && !"".equals(name)) //$NON-NLS-1$
1643:                        fNewMethodName = name;
1644:                    else
1645:                        return RefactoringStatus
1646:                                .createFatalErrorStatus(Messages
1647:                                        .format(
1648:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1649:                                                JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME));
1650:                    final String protect = extended
1651:                            .getAttribute(ATTRIBUTE_PROTECT);
1652:                    if (protect != null) {
1653:                        fProtectConstructor = Boolean.valueOf(protect)
1654:                                .booleanValue();
1655:                    } else
1656:                        return RefactoringStatus
1657:                                .createFatalErrorStatus(Messages
1658:                                        .format(
1659:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1660:                                                ATTRIBUTE_PROTECT));
1661:                } else
1662:                    return RefactoringStatus
1663:                            .createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
1664:                return new RefactoringStatus();
1665:            }
1666:        }
w_w__w___.___jav_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.