KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > structure > IntroduceParameterObjectRefactoring


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.refactoring.structure;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.HashMap JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.List JavaDoc;
17 import java.util.Map JavaDoc;
18
19 import org.eclipse.text.edits.TextEdit;
20
21 import org.eclipse.core.runtime.Assert;
22 import org.eclipse.core.runtime.CoreException;
23 import org.eclipse.core.runtime.IProgressMonitor;
24 import org.eclipse.core.runtime.IStatus;
25 import org.eclipse.core.runtime.OperationCanceledException;
26 import org.eclipse.core.runtime.Status;
27
28 import org.eclipse.jface.text.BadLocationException;
29 import org.eclipse.jface.text.Document;
30
31 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
32 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
33
34 import org.eclipse.jdt.core.ICompilationUnit;
35 import org.eclipse.jdt.core.IJavaElement;
36 import org.eclipse.jdt.core.IJavaProject;
37 import org.eclipse.jdt.core.IMethod;
38 import org.eclipse.jdt.core.IPackageFragment;
39 import org.eclipse.jdt.core.IPackageFragmentRoot;
40 import org.eclipse.jdt.core.JavaModelException;
41 import org.eclipse.jdt.core.NamingConventions;
42 import org.eclipse.jdt.core.ToolFactory;
43 import org.eclipse.jdt.core.compiler.IProblem;
44 import org.eclipse.jdt.core.compiler.IScanner;
45 import org.eclipse.jdt.core.compiler.ITerminalSymbols;
46 import org.eclipse.jdt.core.compiler.InvalidInputException;
47 import org.eclipse.jdt.core.dom.AST;
48 import org.eclipse.jdt.core.dom.ASTNode;
49 import org.eclipse.jdt.core.dom.ASTVisitor;
50 import org.eclipse.jdt.core.dom.ArrayCreation;
51 import org.eclipse.jdt.core.dom.ArrayInitializer;
52 import org.eclipse.jdt.core.dom.ArrayType;
53 import org.eclipse.jdt.core.dom.Block;
54 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
55 import org.eclipse.jdt.core.dom.CompilationUnit;
56 import org.eclipse.jdt.core.dom.Expression;
57 import org.eclipse.jdt.core.dom.ExpressionStatement;
58 import org.eclipse.jdt.core.dom.FieldAccess;
59 import org.eclipse.jdt.core.dom.IBinding;
60 import org.eclipse.jdt.core.dom.IMethodBinding;
61 import org.eclipse.jdt.core.dom.ITypeBinding;
62 import org.eclipse.jdt.core.dom.IVariableBinding;
63 import org.eclipse.jdt.core.dom.Javadoc;
64 import org.eclipse.jdt.core.dom.Message;
65 import org.eclipse.jdt.core.dom.MethodDeclaration;
66 import org.eclipse.jdt.core.dom.Name;
67 import org.eclipse.jdt.core.dom.NullLiteral;
68 import org.eclipse.jdt.core.dom.QualifiedName;
69 import org.eclipse.jdt.core.dom.SimpleName;
70 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
71 import org.eclipse.jdt.core.dom.SuperFieldAccess;
72 import org.eclipse.jdt.core.dom.Type;
73 import org.eclipse.jdt.core.dom.TypeDeclaration;
74 import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
75 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
76 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
77 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
78
79 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
80 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
81 import org.eclipse.jdt.internal.corext.dom.NodeFinder;
82 import org.eclipse.jdt.internal.corext.dom.TokenScanner;
83 import org.eclipse.jdt.internal.corext.dom.TypeBindingVisitor;
84 import org.eclipse.jdt.internal.corext.refactoring.Checks;
85 import org.eclipse.jdt.internal.corext.refactoring.ParameterInfo;
86 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
87 import org.eclipse.jdt.internal.corext.refactoring.TypeContextChecker.IProblemVerifier;
88 import org.eclipse.jdt.internal.corext.refactoring.changes.CreateCompilationUnitChange;
89 import org.eclipse.jdt.internal.corext.refactoring.changes.CreatePackageChange;
90 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
91 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
92 import org.eclipse.jdt.internal.corext.util.Messages;
93
94 import org.eclipse.jdt.ui.CodeGeneration;
95
96 import org.eclipse.jdt.internal.ui.JavaPlugin;
97 import org.eclipse.jdt.internal.ui.text.correction.ASTResolving;
98
99 public class IntroduceParameterObjectRefactoring extends ChangeSignatureRefactoring {
100
101     private final class ParameterObjectCreator implements IDefaultValueAdvisor {
102         public Expression createDefaultExpression(List JavaDoc invocationArguments, ParameterInfo addedInfo, List JavaDoc parameterInfos,
103                 MethodDeclaration enclosingMethod, boolean isRecursive, CompilationUnitRewrite cuRewrite) {
104             final AST ast= cuRewrite.getAST();
105             final ASTRewrite rewrite= cuRewrite.getASTRewrite();
106             if (isRecursive && canReuseParameterObject(invocationArguments, addedInfo, parameterInfos, enclosingMethod)) {
107                 return ast.newSimpleName(addedInfo.getNewName());
108             }
109             ClassInstanceCreation classCreation= ast.newClassInstanceCreation();
110
111             int startPosition= enclosingMethod != null ? enclosingMethod.getStartPosition() : cuRewrite.getRoot().getStartPosition();
112             classCreation.setType(fParameterObjectFactory.createType(fCreateAsTopLevel, cuRewrite, startPosition));
113             List JavaDoc constructorArguments= classCreation.arguments();
114             for (Iterator JavaDoc iter= parameterInfos.iterator(); iter.hasNext();) {
115                 ParameterInfo pi= (ParameterInfo) iter.next();
116                 if (isValidField(pi)) {
117                     if (pi.isOldVarargs()) {
118                         boolean isLastParameter= !iter.hasNext();
119                         constructorArguments.addAll(computeVarargs(invocationArguments, pi, isLastParameter, cuRewrite));
120                     } else {
121                         Expression exp= (Expression) invocationArguments.get(pi.getOldIndex());
122                         importNodeTypes(exp, cuRewrite);
123                         constructorArguments.add(moveNode(exp, rewrite));
124                     }
125                 }
126             }
127             return classCreation;
128         }
129
130         public Type createType(String JavaDoc newTypeName, int startPosition, CompilationUnitRewrite cuRewrite) {
131             return fParameterObjectFactory.createType(fCreateAsTopLevel, cuRewrite, startPosition);
132         }
133
134         private boolean canReuseParameterObject(List JavaDoc invocationArguments, ParameterInfo addedInfo, List JavaDoc parameterInfos,
135                 MethodDeclaration enclosingMethod) {
136             Assert.isNotNull(enclosingMethod);
137             List JavaDoc parameters= enclosingMethod.parameters();
138             for (Iterator JavaDoc iter= parameterInfos.iterator(); iter.hasNext();) {
139                 ParameterInfo pi= (ParameterInfo) iter.next();
140                 if (isValidField(pi)) {
141                     if (!pi.isInlined())
142                         return false;
143                     ASTNode node= (ASTNode) invocationArguments.get(pi.getOldIndex());
144                     if (!isParameter(pi, node, parameters, addedInfo.getNewName())) {
145                         return false;
146                     }
147                 }
148             }
149             return true;
150         }
151
152         private List JavaDoc computeVarargs(List JavaDoc invocationArguments, ParameterInfo varArgPI, boolean isLastParameter, CompilationUnitRewrite cuRewrite) {
153             boolean isEmptyVarArg= varArgPI.getOldIndex() >= invocationArguments.size();
154             ASTRewrite rewrite= cuRewrite.getASTRewrite();
155             AST ast= cuRewrite.getAST();
156             ASTNode lastNode= isEmptyVarArg ? null : (ASTNode) invocationArguments.get(varArgPI.getOldIndex());
157             List JavaDoc constructorArguments= new ArrayList JavaDoc();
158             if (lastNode instanceof ArrayCreation) {
159                 ArrayCreation creation= (ArrayCreation) lastNode;
160                 ITypeBinding arrayType= creation.resolveTypeBinding();
161                 if (arrayType != null && arrayType.isAssignmentCompatible(varArgPI.getNewTypeBinding())) {
162                     constructorArguments.add(moveNode(creation, rewrite));
163                     return constructorArguments;
164                 }
165             }
166             if (isLastParameter) {
167                 // copy all varargs
168
for (int i= varArgPI.getOldIndex(); i < invocationArguments.size(); i++) {
169                     ASTNode node= (ASTNode) invocationArguments.get(i);
170                     importNodeTypes(node, cuRewrite);
171                     constructorArguments.add(moveNode(node, rewrite));
172                 }
173             } else { // new signature would be String...args, int
174
if (lastNode instanceof NullLiteral) {
175                     NullLiteral nullLiteral= (NullLiteral) lastNode;
176                     constructorArguments.add(moveNode(nullLiteral, rewrite));
177                 } else {
178                     ArrayCreation creation= ast.newArrayCreation();
179                     creation.setType((ArrayType) importBinding(varArgPI.getNewTypeBinding(), cuRewrite));
180                     ArrayInitializer initializer= ast.newArrayInitializer();
181                     List JavaDoc expressions= initializer.expressions();
182                     for (int i= varArgPI.getOldIndex(); i < invocationArguments.size(); i++) {
183                         ASTNode node= (ASTNode) invocationArguments.get(i);
184                         importNodeTypes(node, cuRewrite);
185                         expressions.add(moveNode(node, rewrite));
186                     }
187                     if (expressions.isEmpty())
188                         creation.dimensions().add(ast.newNumberLiteral("0")); //$NON-NLS-1$
189
else
190                         creation.setInitializer(initializer);
191                     constructorArguments.add(creation);
192                 }
193             }
194             return constructorArguments;
195         }
196
197         public Type importBinding(ITypeBinding newTypeBinding, CompilationUnitRewrite cuRewrite) {
198             Type type= cuRewrite.getImportRewrite().addImport(newTypeBinding, cuRewrite.getAST());
199             cuRewrite.getImportRemover().registerAddedImports(type);
200             return type;
201         }
202
203         private void importNodeTypes(ASTNode node, final CompilationUnitRewrite cuRewrite) {
204             ASTResolving.visitAllBindings(node, new TypeBindingVisitor() {
205                 public boolean visit(ITypeBinding nodeBinding) {
206                     importBinding(nodeBinding, cuRewrite);
207                     return false;
208                 }
209             });
210         }
211     }
212
213     private boolean isParameter(ParameterInfo pi, ASTNode node, List JavaDoc enclosingMethodParameters, String JavaDoc qualifier) {
214         if (node instanceof Name) {
215             Name name= (Name) node;
216             IVariableBinding binding= ASTNodes.getVariableBinding(name);
217             if (binding != null && binding.isParameter()) {
218                 return binding.getName().equals(getNameInScope(pi, enclosingMethodParameters));
219             } else {
220                 if (node instanceof QualifiedName) {
221                     QualifiedName qn= (QualifiedName) node;
222                     return qn.getFullyQualifiedName().equals(JavaModelUtil.concatenateName(qualifier, getNameInScope(pi, enclosingMethodParameters)));
223                 }
224             }
225         }
226         return false;
227     }
228
229     private final class RewriteParameterBody extends BodyUpdater {
230         private boolean fParameterClassCreated= false;
231
232         public void updateBody(MethodDeclaration methodDeclaration, CompilationUnitRewrite cuRewrite, RefactoringStatus result) throws CoreException {
233             // ensure that the parameterObject is imported
234
fParameterObjectFactory.createType(fCreateAsTopLevel, cuRewrite, methodDeclaration.getStartPosition());
235             if (cuRewrite.getCu().equals(fCompilationUnit) && !fParameterClassCreated) {
236                 createParameterClass(methodDeclaration, cuRewrite);
237                 fParameterClassCreated= true;
238             }
239             Block body= methodDeclaration.getBody();
240             final List JavaDoc parameters= methodDeclaration.parameters();
241             if (body != null) { // abstract methods don't have bodies
242
final ASTRewrite rewriter= cuRewrite.getASTRewrite();
243                 ListRewrite bodyStatements= rewriter.getListRewrite(body, Block.STATEMENTS_PROPERTY);
244                 List JavaDoc managedParams= getParameterInfos();
245                 for (Iterator JavaDoc iter= managedParams.iterator(); iter.hasNext();) {
246                     final ParameterInfo pi= (ParameterInfo) iter.next();
247                     if (isValidField(pi)) {
248                         if (isReadOnly(pi, body, parameters, null)) {
249                             body.accept(new ASTVisitor(false) {
250
251                                 public boolean visit(SimpleName node) {
252                                     updateSimpleName(rewriter, pi, node, parameters);
253                                     return false;
254                                 }
255
256                             });
257                             pi.setInlined(true);
258                         } else {
259                             ExpressionStatement initializer= fParameterObjectFactory.createInitializer(pi, getParameterName(), cuRewrite);
260                             bodyStatements.insertFirst(initializer, null);
261                         }
262                     }
263                 }
264             }
265
266
267         }
268
269         private void updateSimpleName(ASTRewrite rewriter, ParameterInfo pi, SimpleName node, List JavaDoc enclosingParameters) {
270             AST ast= rewriter.getAST();
271             IBinding binding= node.resolveBinding();
272             Expression replacementNode= fParameterObjectFactory.createFieldReadAccess(pi, getParameterName(), ast);
273             if (binding instanceof IVariableBinding) {
274                 IVariableBinding variable= (IVariableBinding) binding;
275                 if (variable.isParameter() && variable.getName().equals(getNameInScope(pi, enclosingParameters))) {
276                     rewriter.replace(node, replacementNode, null);
277                 }
278             } else {
279                 ASTNode parent= node.getParent();
280                 if (! (parent instanceof QualifiedName || parent instanceof FieldAccess || parent instanceof SuperFieldAccess)) {
281                     if (node.getIdentifier().equals(getNameInScope(pi, enclosingParameters))) {
282                         rewriter.replace(node, replacementNode, null);
283                     }
284                 }
285             }
286         }
287
288         private boolean isReadOnly(final ParameterInfo pi, Block block, final List JavaDoc enclosingMethodParameters, final String JavaDoc qualifier) {
289             class NotWrittenDetector extends ASTVisitor {
290                 boolean notWritten= true;
291
292                 public boolean visit(SimpleName node) {
293                     if (isParameter(pi, node, enclosingMethodParameters, qualifier) && ASTResolving.isWriteAccess(node))
294                         notWritten= false;
295                     return false;
296                 }
297
298                 public boolean visit(SuperFieldAccess node) {
299                     return false;
300                 }
301             }
302             NotWrittenDetector visitor= new NotWrittenDetector();
303             block.accept(visitor);
304             return visitor.notWritten;
305         }
306
307         public boolean needsParameterUsedCheck() {
308             return false;
309         }
310
311     }
312
313     private static final String JavaDoc PARAMETER_CLASS_APPENDIX= "Parameter"; //$NON-NLS-1$
314

315     private static final String JavaDoc DEFAULT_PARAMETER_OBJECT_NAME= "parameterObject"; //$NON-NLS-1$
316

317     private MethodDeclaration fMethodDeclaration;
318
319     private ICompilationUnit fCompilationUnit;
320
321     private int fOffset;
322
323     private int fLength;
324
325     private ParameterObjectFactory fParameterObjectFactory;
326
327     private boolean fCreateAsTopLevel= true;
328
329     private ParameterInfo fParameterObjectReference;
330
331     public IntroduceParameterObjectRefactoring(IMethod method) throws JavaModelException {
332         super(method);
333         Assert.isNotNull(method);
334         initializeFields(method);
335         setBodyUpdater(new RewriteParameterBody());
336         setDefaultValueAdvisor(new ParameterObjectCreator());
337         List JavaDoc parameterInfos= getParameterInfos();
338         for (Iterator JavaDoc iter= parameterInfos.iterator(); iter.hasNext();) {
339             ParameterInfo pi= (ParameterInfo) iter.next();
340             if (!pi.isAdded()) {
341                 pi.setCreateField(true);
342                 pi.setNewName(getFieldName(pi));
343             }
344         }
345     }
346
347     private void initializeFields(IMethod method) throws JavaModelException {
348         fCompilationUnit= method.getCompilationUnit();
349         Assert.isNotNull(fCompilationUnit);
350         fOffset= method.getNameRange().getOffset();
351         fLength= method.getNameRange().getLength();
352         fParameterObjectFactory= new ParameterObjectFactory(fCompilationUnit);
353         String JavaDoc methodName= method.getElementName();
354         String JavaDoc className= String.valueOf(Character.toUpperCase(methodName.charAt(0)));
355         if (methodName.length() > 1)
356             className+= methodName.substring(1);
357         className+= PARAMETER_CLASS_APPENDIX;
358         fParameterObjectReference= ParameterInfo.createInfoForAddedParameter(className, DEFAULT_PARAMETER_OBJECT_NAME);
359         fParameterObjectFactory.setClassName(className);
360         fParameterObjectFactory.setPackage(method.getDeclaringType().getPackageFragment().getElementName());
361         updateReferenceType();
362     }
363
364     public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException {
365         RefactoringStatus status= new RefactoringStatus();
366         status.merge(fParameterObjectFactory.checkConditions());
367         status.merge(Checks.checkIdentifier(getParameterName()));
368         if (status.hasFatalError())
369             return status;
370         status.merge(super.checkFinalConditions(pm));
371         return status;
372     }
373
374     public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException {
375         RefactoringStatus status= new RefactoringStatus();
376         status.merge(super.checkInitialConditions(pm));
377         status.merge(Checks.checkAvailability(fCompilationUnit));
378         if (status.hasFatalError())
379             return status;
380         CompilationUnit astRoot= getBaseCuRewrite().getRoot();
381         ASTNode selectedNode= NodeFinder.perform(astRoot, fOffset, fLength);
382         if (selectedNode == null) {
383             return mappingErrorFound(status, selectedNode);
384         }
385         fMethodDeclaration= (MethodDeclaration) ASTNodes.getParent(selectedNode, MethodDeclaration.class);
386         if (fMethodDeclaration == null) {
387             return mappingErrorFound(status, selectedNode);
388         }
389         IMethodBinding resolveBinding= fMethodDeclaration.resolveBinding();
390         if (resolveBinding == null) {
391             if (!processCompilerError(status, selectedNode))
392                 status.addFatalError(RefactoringCoreMessages.SelfEncapsulateField_type_not_resolveable);
393             return status;
394         }
395
396         ITypeBinding declaringClass= resolveBinding.getDeclaringClass();
397         if (fParameterObjectFactory.getPackage() == null)
398             fParameterObjectFactory.setPackage(declaringClass.getPackage().getName());
399         if (fParameterObjectFactory.getEnclosingType() == null)
400             fParameterObjectFactory.setEnclosingType(declaringClass.getQualifiedName());
401
402         List JavaDoc parameterInfos= super.getParameterInfos();
403         if (!parameterInfos.contains(fParameterObjectReference)) {
404             parameterInfos.add(0, fParameterObjectReference);
405         }
406         Map JavaDoc bindingMap= new HashMap JavaDoc();
407         for (Iterator JavaDoc iter= fMethodDeclaration.parameters().iterator(); iter.hasNext();) {
408             SingleVariableDeclaration sdv= (SingleVariableDeclaration) iter.next();
409             bindingMap.put(sdv.getName().getIdentifier(), sdv.resolveBinding());
410         }
411         for (Iterator JavaDoc iter= parameterInfos.iterator(); iter.hasNext();) {
412             ParameterInfo pi= (ParameterInfo) iter.next();
413             if (pi != fParameterObjectReference)
414                 pi.setOldBinding((IVariableBinding) bindingMap.get(pi.getOldName()));
415         }
416         fParameterObjectFactory.setVariables(parameterInfos);
417         return status;
418     }
419
420     protected IProblemVerifier doGetProblemVerifier() {
421         return new IProblemVerifier() {
422
423             public boolean isError(IProblem problem, ASTNode node) {
424                 if (node instanceof Type) {
425                     Type type= (Type) node;
426                     if (problem.getID() == IProblem.UndefinedType && getClassName().equals(ASTNodes.getTypeName(type))) {
427                         return false;
428                     }
429                 }
430                 if (node instanceof Name) {
431                     Name name= (Name) node;
432                     if (problem.getID() == IProblem.ImportNotFound && getPackage().indexOf(name.getFullyQualifiedName()) != -1)
433                         return false;
434                 }
435                 return true;
436             }
437
438         };
439     }
440
441     public String JavaDoc getClassName() {
442         return fParameterObjectFactory.getClassName();
443     }
444
445     public ITypeBinding getContainingClass() {
446         return fMethodDeclaration.resolveBinding().getDeclaringClass();
447     }
448
449     private String JavaDoc getMappingErrorMessage() {
450         return Messages.format(RefactoringCoreMessages.IntroduceParameterObjectRefactoring_cannotalanyzemethod_mappingerror, new String JavaDoc[] {});
451     }
452
453     public String JavaDoc getFieldName(ParameterInfo element) {
454         String JavaDoc paramName= element.getOldName();
455         IJavaProject javaProject= fCompilationUnit.getJavaProject();
456         String JavaDoc stripped= NamingConventions.removePrefixAndSuffixForArgumentName(javaProject, paramName);
457         int dim= element.getNewTypeBinding() != null ? element.getNewTypeBinding().getDimensions() : 0;
458         return StubUtility.getVariableNameSuggestions(StubUtility.INSTANCE_FIELD, javaProject, stripped, dim, null, true)[0];
459     }
460
461
462     public String JavaDoc getName() {
463         return RefactoringCoreMessages.IntroduceParameterObjectRefactoring_refactoring_name;
464     }
465
466     protected String JavaDoc doGetRefactoringChangeName() {
467         return getName();
468     }
469
470     public String JavaDoc getParameterName() {
471         return fParameterObjectReference.getNewName();
472     }
473
474     public RefactoringStatus initialize(RefactoringArguments arguments) {
475         RefactoringStatus refactoringStatus= new RefactoringStatus();
476         refactoringStatus.merge(super.initialize(arguments));
477         return refactoringStatus;
478     }
479
480     public boolean isCreateGetter() {
481         return fParameterObjectFactory.isCreateGetter();
482     }
483
484     public boolean isCreateSetter() {
485         return fParameterObjectFactory.isCreateSetter();
486     }
487
488     public boolean isCreateAsTopLevel() {
489         return fCreateAsTopLevel;
490     }
491
492     /**
493      * Checks if the given parameter info has been selected for field creation
494      *
495      * @param pi parameter info
496      * @return true if the given parameter info has been selected for field creation
497      */

498     private boolean isValidField(ParameterInfo pi) {
499         return pi.isCreateField() & !pi.isAdded();
500     }
501
502     private RefactoringStatus mappingErrorFound(RefactoringStatus result, ASTNode node) {
503         if (node != null && (node.getFlags() & ASTNode.MALFORMED) != 0 && processCompilerError(result, node))
504             return result;
505         result.addFatalError(getMappingErrorMessage());
506         return result;
507     }
508
509     public void moveFieldDown(ParameterInfo selected) {
510         fParameterObjectFactory.moveDown(selected);
511     }
512
513     public void moveFieldUp(ParameterInfo selected) {
514         fParameterObjectFactory.moveUp(selected);
515     }
516
517     private boolean processCompilerError(RefactoringStatus result, ASTNode node) {
518         Message[] messages= ASTNodes.getMessages(node, ASTNodes.INCLUDE_ALL_PARENTS);
519         if (messages.length == 0)
520             return false;
521         result.addFatalError(Messages.format(RefactoringCoreMessages.IntroduceParameterObjectRefactoring_cannotanalysemethod_compilererror,
522                 new String JavaDoc[] { messages[0].getMessage() }));
523         return true;
524     }
525
526     public void setClassName(String JavaDoc className) {
527         fParameterObjectFactory.setClassName(className);
528         updateReferenceType();
529     }
530
531     private void updateReferenceType() {
532         if (fCreateAsTopLevel)
533             fParameterObjectReference.setNewTypeName(JavaModelUtil.concatenateName(fParameterObjectFactory.getPackage(), fParameterObjectFactory
534                     .getClassName()));
535         else
536             fParameterObjectReference.setNewTypeName(JavaModelUtil.concatenateName(fParameterObjectFactory.getEnclosingType(),
537                     fParameterObjectFactory.getClassName()));
538     }
539
540     public void setCreateComments(boolean selection) {
541         fParameterObjectFactory.setCreateComments(selection);
542     }
543
544     public void setCreateGetter(boolean createGetter) {
545         fParameterObjectFactory.setCreateGetter(createGetter);
546     }
547
548     public void setCreateSetter(boolean createSetter) {
549         fParameterObjectFactory.setCreateSetter(createSetter);
550     }
551
552     public void setPackageName(String JavaDoc packageName) {
553         fParameterObjectFactory.setPackage(packageName);
554         updateReferenceType();
555     }
556
557     public void setParameterName(String JavaDoc paramName) {
558         this.fParameterObjectReference.setNewName(paramName);
559     }
560
561     public void setCreateAsTopLevel(boolean topLevel) {
562         this.fCreateAsTopLevel= topLevel;
563         updateReferenceType();
564     }
565
566     public void updateParameterPosition() {
567         fParameterObjectFactory.updateParameterPosition(fParameterObjectReference);
568     }
569
570     private void createParameterClass(MethodDeclaration methodDeclaration, CompilationUnitRewrite cuRewrite) throws CoreException {
571         if (fCreateAsTopLevel) {
572             IJavaProject javaProject= fCompilationUnit.getJavaProject();
573             IPackageFragment packageFragment= getPackageFragmentRoot().getPackageFragment(fParameterObjectFactory.getPackage());
574             if (!packageFragment.exists()) {
575                 fOtherChanges.add(new CreatePackageChange(packageFragment));
576             }
577
578             ICompilationUnit unit= packageFragment.getCompilationUnit(fParameterObjectFactory.getClassName() + ".java"); //$NON-NLS-1$
579
Assert.isTrue(!unit.exists());
580             createTopLevelParameterObject(javaProject, unit);
581         } else {
582             ASTRewrite rewriter= cuRewrite.getASTRewrite();
583             TypeDeclaration enclosingType= (TypeDeclaration) methodDeclaration.getParent();
584             ListRewrite bodyRewrite= rewriter.getListRewrite(enclosingType, TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
585             TypeDeclaration classDeclaration= fParameterObjectFactory.createClassDeclaration(fCompilationUnit, enclosingType.getName()
586                     .getFullyQualifiedName(), cuRewrite);
587             classDeclaration.modifiers().add(rewriter.getAST().newModifier(ModifierKeyword.PUBLIC_KEYWORD));
588             classDeclaration.modifiers().add(rewriter.getAST().newModifier(ModifierKeyword.STATIC_KEYWORD));
589             bodyRewrite.insertBefore(classDeclaration, methodDeclaration, null);
590         }
591     }
592
593     private void createTopLevelParameterObject(IJavaProject javaProject, ICompilationUnit unit) throws JavaModelException, CoreException {
594         ICompilationUnit workingCopy= unit.getWorkingCopy(null);
595
596         try {
597             // create stub with comments and dummy type
598
String JavaDoc lineDelimiter= StubUtility.getLineDelimiterUsed(javaProject);
599             String JavaDoc fileComment= getFileComment(workingCopy, lineDelimiter);
600             String JavaDoc typeComment= getTypeComment(workingCopy, lineDelimiter);
601             String JavaDoc content= CodeGeneration.getCompilationUnitContent(workingCopy, fileComment, typeComment,
602                     "class " + getClassName() + "{}", lineDelimiter); //$NON-NLS-1$ //$NON-NLS-2$
603
workingCopy.getBuffer().setContents(content);
604
605             CompilationUnitRewrite cuRewrite= new CompilationUnitRewrite(workingCopy);
606             ASTRewrite rewriter= cuRewrite.getASTRewrite();
607             CompilationUnit root= cuRewrite.getRoot();
608             AST ast= cuRewrite.getAST();
609             ImportRewrite importRewrite= cuRewrite.getImportRewrite();
610
611             // retrieve&replace dummy type with real class
612
ListRewrite types= rewriter.getListRewrite(root, CompilationUnit.TYPES_PROPERTY);
613             ASTNode dummyType= (ASTNode) types.getOriginalList().get(0);
614             String JavaDoc newTypeName= JavaModelUtil.concatenateName(fParameterObjectFactory.getPackage(), fParameterObjectFactory.getClassName());
615             TypeDeclaration classDeclaration= fParameterObjectFactory.createClassDeclaration(workingCopy, newTypeName, cuRewrite);
616             classDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD));
617             Javadoc javadoc= (Javadoc) dummyType.getStructuralProperty(TypeDeclaration.JAVADOC_PROPERTY);
618             rewriter.set(classDeclaration, TypeDeclaration.JAVADOC_PROPERTY, javadoc, null);
619             types.replace(dummyType, classDeclaration, null);
620
621             // Apply rewrites and discard workingcopy
622
// Using CompilationUnitRewrite.createChange() leads to strange
623
// results
624
String JavaDoc charset= ResourceUtil.getFile(fCompilationUnit).getCharset(false);
625             Document document= new Document(content);
626             try {
627                 rewriter.rewriteAST().apply(document);
628                 TextEdit rewriteImports= importRewrite.rewriteImports(null);
629                 rewriteImports.apply(document);
630             } catch (BadLocationException e) {
631                 throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(),
632                         RefactoringCoreMessages.IntroduceParameterObjectRefactoring_parameter_object_creation_error, e));
633             }
634             String JavaDoc docContent= document.get();
635             CreateCompilationUnitChange compilationUnitChange= new CreateCompilationUnitChange(unit, docContent, charset);
636             fOtherChanges.add(compilationUnitChange);
637         } finally {
638             workingCopy.discardWorkingCopy();
639         }
640     }
641
642     public IPackageFragmentRoot getPackageFragmentRoot() {
643         return (IPackageFragmentRoot) fCompilationUnit.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
644     }
645
646     protected String JavaDoc getFileComment(ICompilationUnit parentCU, String JavaDoc lineDelimiter) throws CoreException {
647         if (fParameterObjectFactory.isCreateComments()) {
648             return CodeGeneration.getFileComment(parentCU, lineDelimiter);
649         }
650         return null;
651
652     }
653
654     protected String JavaDoc getTypeComment(ICompilationUnit parentCU, String JavaDoc lineDelimiter) throws CoreException {
655         if (fParameterObjectFactory.isCreateComments()) {
656             StringBuffer JavaDoc typeName= new StringBuffer JavaDoc();
657             typeName.append(fParameterObjectFactory.getClassName());
658             String JavaDoc[] typeParamNames= new String JavaDoc[0];
659             String JavaDoc comment= CodeGeneration.getTypeComment(parentCU, typeName.toString(), typeParamNames, lineDelimiter);
660             if (comment != null && isValidComment(comment)) {
661                 return comment;
662             }
663         }
664         return null;
665     }
666
667     private boolean isValidComment(String JavaDoc template) {
668         IScanner scanner= ToolFactory.createScanner(true, false, false, false);
669         scanner.setSource(template.toCharArray());
670         try {
671             int next= scanner.getNextToken();
672             while (TokenScanner.isComment(next)) {
673                 next= scanner.getNextToken();
674             }
675             return next == ITerminalSymbols.TokenNameEOF;
676         } catch (InvalidInputException e) {
677         }
678         return false;
679     }
680
681     public String JavaDoc getPackage() {
682         return fParameterObjectFactory.getPackage();
683     }
684
685     public void setPackage(String JavaDoc typeQualifier) {
686         fParameterObjectFactory.setPackage(typeQualifier);
687     }
688
689     public ICompilationUnit getCompilationUnit() {
690         return fCompilationUnit;
691     }
692
693     private String JavaDoc getNameInScope(ParameterInfo pi, List JavaDoc enclosingMethodParameters) {
694         Assert.isNotNull(enclosingMethodParameters);
695         boolean emptyVararg= pi.getOldIndex() >= enclosingMethodParameters.size();
696         if (!emptyVararg) {
697             SingleVariableDeclaration svd= (SingleVariableDeclaration) enclosingMethodParameters.get(pi.getOldIndex());
698             return svd.getName().getIdentifier();
699         }
700         return null;
701     }
702
703     public String JavaDoc getNewTypeName() {
704         return fParameterObjectReference.getNewTypeName();
705     }
706
707 }
708
Popular Tags