KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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.Arrays JavaDoc;
15 import java.util.Collection JavaDoc;
16 import java.util.HashMap JavaDoc;
17 import java.util.HashSet JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.LinkedHashMap JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Map JavaDoc;
22 import java.util.Set JavaDoc;
23
24 import org.eclipse.text.edits.TextEdit;
25 import org.eclipse.text.edits.TextEditGroup;
26
27 import org.eclipse.core.runtime.Assert;
28 import org.eclipse.core.runtime.CoreException;
29 import org.eclipse.core.runtime.IProgressMonitor;
30 import org.eclipse.core.runtime.NullProgressMonitor;
31 import org.eclipse.core.runtime.SubProgressMonitor;
32
33 import org.eclipse.ltk.core.refactoring.Change;
34 import org.eclipse.ltk.core.refactoring.IRefactoringStatusEntryComparator;
35 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
36 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
37 import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry;
38 import org.eclipse.ltk.core.refactoring.TextChange;
39 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
40
41 import org.eclipse.jdt.core.Flags;
42 import org.eclipse.jdt.core.ICompilationUnit;
43 import org.eclipse.jdt.core.IField;
44 import org.eclipse.jdt.core.IJavaElement;
45 import org.eclipse.jdt.core.IJavaProject;
46 import org.eclipse.jdt.core.IMethod;
47 import org.eclipse.jdt.core.IType;
48 import org.eclipse.jdt.core.ITypeHierarchy;
49 import org.eclipse.jdt.core.ITypeParameter;
50 import org.eclipse.jdt.core.JavaModelException;
51 import org.eclipse.jdt.core.dom.AST;
52 import org.eclipse.jdt.core.dom.ASTNode;
53 import org.eclipse.jdt.core.dom.ASTParser;
54 import org.eclipse.jdt.core.dom.ASTVisitor;
55 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
56 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
57 import org.eclipse.jdt.core.dom.Assignment;
58 import org.eclipse.jdt.core.dom.Block;
59 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
60 import org.eclipse.jdt.core.dom.CompilationUnit;
61 import org.eclipse.jdt.core.dom.ConstructorInvocation;
62 import org.eclipse.jdt.core.dom.EnumDeclaration;
63 import org.eclipse.jdt.core.dom.Expression;
64 import org.eclipse.jdt.core.dom.FieldAccess;
65 import org.eclipse.jdt.core.dom.FieldDeclaration;
66 import org.eclipse.jdt.core.dom.IBinding;
67 import org.eclipse.jdt.core.dom.IMethodBinding;
68 import org.eclipse.jdt.core.dom.ITypeBinding;
69 import org.eclipse.jdt.core.dom.IVariableBinding;
70 import org.eclipse.jdt.core.dom.ImportDeclaration;
71 import org.eclipse.jdt.core.dom.Javadoc;
72 import org.eclipse.jdt.core.dom.MethodDeclaration;
73 import org.eclipse.jdt.core.dom.MethodInvocation;
74 import org.eclipse.jdt.core.dom.Modifier;
75 import org.eclipse.jdt.core.dom.Name;
76 import org.eclipse.jdt.core.dom.ParameterizedType;
77 import org.eclipse.jdt.core.dom.QualifiedName;
78 import org.eclipse.jdt.core.dom.QualifiedType;
79 import org.eclipse.jdt.core.dom.SimpleName;
80 import org.eclipse.jdt.core.dom.SimpleType;
81 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
82 import org.eclipse.jdt.core.dom.Statement;
83 import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
84 import org.eclipse.jdt.core.dom.ThisExpression;
85 import org.eclipse.jdt.core.dom.Type;
86 import org.eclipse.jdt.core.dom.TypeDeclaration;
87 import org.eclipse.jdt.core.dom.TypeDeclarationStatement;
88 import org.eclipse.jdt.core.dom.TypeParameter;
89 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
90 import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
91 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
92 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
93 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
94 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
95 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
96 import org.eclipse.jdt.core.search.IJavaSearchConstants;
97 import org.eclipse.jdt.core.search.SearchMatch;
98 import org.eclipse.jdt.core.search.SearchPattern;
99
100 import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
101 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
102 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
103 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
104 import org.eclipse.jdt.internal.corext.dom.Bindings;
105 import org.eclipse.jdt.internal.corext.dom.ModifierRewrite;
106 import org.eclipse.jdt.internal.corext.refactoring.Checks;
107 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor;
108 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
109 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
110 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
111 import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory;
112 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine2;
113 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
114 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
115 import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange;
116 import org.eclipse.jdt.internal.corext.refactoring.changes.CreateCompilationUnitChange;
117 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
118 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
119 import org.eclipse.jdt.internal.corext.refactoring.structure.MemberVisibilityAdjustor.OutgoingMemberVisibilityAdjustment;
120 import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
121 import org.eclipse.jdt.internal.corext.refactoring.util.JavadocUtil;
122 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
123 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
124 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
125 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
126 import org.eclipse.jdt.internal.corext.util.JdtFlags;
127 import org.eclipse.jdt.internal.corext.util.Messages;
128 import org.eclipse.jdt.internal.corext.util.SearchUtils;
129 import org.eclipse.jdt.internal.corext.util.Strings;
130
131 import org.eclipse.jdt.ui.CodeGeneration;
132 import org.eclipse.jdt.ui.JavaElementLabels;
133
134 import org.eclipse.jdt.internal.ui.JavaPlugin;
135 import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
136 import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
137
138 public final class MoveInnerToTopRefactoring extends ScriptableRefactoring {
139
140     private static final String JavaDoc ATTRIBUTE_FIELD= "field"; //$NON-NLS-1$
141
private static final String JavaDoc ATTRIBUTE_MANDATORY= "mandatory"; //$NON-NLS-1$
142
private static final String JavaDoc ATTRIBUTE_POSSIBLE= "possible"; //$NON-NLS-1$
143
private static final String JavaDoc ATTRIBUTE_FINAL= "final"; //$NON-NLS-1$
144
private static final String JavaDoc ATTRIBUTE_FIELD_NAME= "fieldName"; //$NON-NLS-1$
145
private static final String JavaDoc ATTRIBUTE_PARAMETER_NAME= "parameterName"; //$NON-NLS-1$
146

147     private static class MemberAccessNodeCollector extends ASTVisitor {
148
149         private final List JavaDoc fFieldAccesses= new ArrayList JavaDoc(0);
150
151         private final ITypeHierarchy fHierarchy;
152
153         private final List JavaDoc fMethodAccesses= new ArrayList JavaDoc(0);
154
155         private final List JavaDoc fSimpleNames= new ArrayList JavaDoc(0);
156
157         MemberAccessNodeCollector(ITypeHierarchy hierarchy) {
158             Assert.isNotNull(hierarchy);
159             fHierarchy= hierarchy;
160         }
161
162         FieldAccess[] getFieldAccesses() {
163             return (FieldAccess[]) fFieldAccesses.toArray(new FieldAccess[fFieldAccesses.size()]);
164         }
165
166         MethodInvocation[] getMethodInvocations() {
167             return (MethodInvocation[]) fMethodAccesses.toArray(new MethodInvocation[fMethodAccesses.size()]);
168         }
169
170         SimpleName[] getSimpleFieldNames() {
171             return (SimpleName[]) fSimpleNames.toArray(new SimpleName[fSimpleNames.size()]);
172         }
173
174         public boolean visit(FieldAccess node) {
175             final ITypeBinding declaring= MoveInnerToTopRefactoring.getDeclaringTypeBinding(node);
176             if (declaring != null) {
177                 final IType type= (IType) declaring.getJavaElement();
178                 if (type != null && fHierarchy.contains(type))
179                     fFieldAccesses.add(node);
180             }
181             return super.visit(node);
182         }
183
184         public boolean visit(MethodInvocation node) {
185             final ITypeBinding declaring= MoveInnerToTopRefactoring.getDeclaringTypeBinding(node);
186             if (declaring != null) {
187                 final IType type= (IType) declaring.getJavaElement();
188                 if (type != null && fHierarchy.contains(type))
189                     fMethodAccesses.add(node);
190             }
191             return super.visit(node);
192         }
193
194         public boolean visit(SimpleName node) {
195             if (node.getParent() instanceof QualifiedName)
196                 return super.visit(node);
197             IBinding binding= node.resolveBinding();
198             if (binding instanceof IVariableBinding) {
199                 IVariableBinding variable= (IVariableBinding) binding;
200                 ITypeBinding declaring= variable.getDeclaringClass();
201                 if (variable.isField() && declaring != null) {
202                     final IType type= (IType) declaring.getJavaElement();
203                     if (type != null && fHierarchy.contains(type)) {
204                         fSimpleNames.add(node);
205                         return false;
206                     }
207                 }
208             }
209             return super.visit(node);
210         }
211
212         public boolean visit(ThisExpression node) {
213             final Name qualifier= node.getQualifier();
214             if (qualifier != null) {
215                 final ITypeBinding binding= qualifier.resolveTypeBinding();
216                 if (binding != null) {
217                     final IType type= (IType) binding.getJavaElement();
218                     if (type != null && fHierarchy.contains(type)) {
219                         fSimpleNames.add(qualifier);
220                         return false;
221                     }
222                 }
223             }
224             return super.visit(node);
225         }
226     }
227
228     private class TypeReferenceQualifier extends ASTVisitor {
229
230         private final TextEditGroup fGroup;
231
232         private final ITypeBinding fTypeBinding;
233
234         public TypeReferenceQualifier(final ITypeBinding type, final TextEditGroup group) {
235             Assert.isNotNull(type);
236             Assert.isNotNull(type.getDeclaringClass());
237             fTypeBinding= type;
238             fGroup= group;
239         }
240
241         public boolean visit(final ClassInstanceCreation node) {
242             Assert.isNotNull(node);
243             if (fCreateInstanceField) {
244                 final AST ast= node.getAST();
245                 final Type type= node.getType();
246                 final ITypeBinding binding= type.resolveBinding();
247                 if (binding != null && binding.getDeclaringClass() != null && !Bindings.equals(binding, fTypeBinding) && fSourceRewrite.getRoot().findDeclaringNode(binding) != null) {
248                     if (!Modifier.isStatic(binding.getModifiers())) {
249                         Expression expression= null;
250                         if (fCodeGenerationSettings.useKeywordThis || fEnclosingInstanceFieldName.equals(fNameForEnclosingInstanceConstructorParameter)) {
251                             final FieldAccess access= ast.newFieldAccess();
252                             access.setExpression(ast.newThisExpression());
253                             access.setName(ast.newSimpleName(fEnclosingInstanceFieldName));
254                             expression= access;
255                         } else
256                             expression= ast.newSimpleName(fEnclosingInstanceFieldName);
257                         if (node.getExpression() != null)
258                             fSourceRewrite.getImportRemover().registerRemovedNode(node.getExpression());
259                         fSourceRewrite.getASTRewrite().set(node, ClassInstanceCreation.EXPRESSION_PROPERTY, expression, fGroup);
260                     } else
261                         addTypeQualification(type, fSourceRewrite, fGroup);
262                 }
263             }
264             return true;
265         }
266
267         public boolean visit(final QualifiedType node) {
268             Assert.isNotNull(node);
269             return false;
270         }
271
272         public boolean visit(final SimpleType node) {
273             Assert.isNotNull(node);
274             if (!(node.getParent() instanceof ClassInstanceCreation)) {
275                 final ITypeBinding binding= node.resolveBinding();
276                 if (binding != null) {
277                     final ITypeBinding declaring= binding.getDeclaringClass();
278                     if (declaring != null && !Bindings.equals(declaring, fTypeBinding.getDeclaringClass()) && !Bindings.equals(binding, fTypeBinding) && fSourceRewrite.getRoot().findDeclaringNode(binding) != null && Modifier.isStatic(binding.getModifiers()))
279                         addTypeQualification(node, fSourceRewrite, fGroup);
280                 }
281             }
282             return super.visit(node);
283         }
284
285         public boolean visit(final ThisExpression node) {
286             Assert.isNotNull(node);
287             final Name name= node.getQualifier();
288             if (name != null && name.isSimpleName()) {
289                 final AST ast= node.getAST();
290                 Expression expression= null;
291                 if (fCodeGenerationSettings.useKeywordThis || fEnclosingInstanceFieldName.equals(fNameForEnclosingInstanceConstructorParameter)) {
292                     final FieldAccess access= ast.newFieldAccess();
293                     access.setExpression(ast.newThisExpression());
294                     access.setName(ast.newSimpleName(fEnclosingInstanceFieldName));
295                     expression= access;
296                 } else
297                     expression= ast.newSimpleName(fEnclosingInstanceFieldName);
298                 fSourceRewrite.getASTRewrite().replace(node, expression, null);
299             }
300             return super.visit(node);
301         }
302     }
303
304     private static void addTypeParameters(final CompilationUnit unit, final IType type, final Map JavaDoc map) throws JavaModelException {
305         Assert.isNotNull(unit);
306         Assert.isNotNull(type);
307         Assert.isNotNull(map);
308         final AbstractTypeDeclaration declaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(type, unit);
309         if (declaration instanceof TypeDeclaration) {
310             ITypeBinding binding= null;
311             TypeParameter parameter= null;
312             for (final Iterator JavaDoc iterator= ((TypeDeclaration) declaration).typeParameters().iterator(); iterator.hasNext();) {
313                 parameter= (TypeParameter) iterator.next();
314                 binding= parameter.resolveBinding();
315                 if (binding != null && !map.containsKey(binding.getKey()))
316                     map.put(binding.getKey(), binding);
317             }
318             final IType declaring= type.getDeclaringType();
319             if (declaring != null && !Flags.isStatic(type.getFlags()))
320                 addTypeParameters(unit, declaring, map);
321         }
322     }
323
324     private static boolean containsNonStatic(FieldAccess[] accesses) {
325         for (int i= 0; i < accesses.length; i++) {
326             if (!isStatic(accesses[i]))
327                 return true;
328         }
329         return false;
330     }
331
332     private static boolean containsNonStatic(MethodInvocation[] invocations) {
333         for (int i= 0; i < invocations.length; i++) {
334             if (!isStatic(invocations[i]))
335                 return true;
336         }
337         return false;
338     }
339
340     private static boolean containsNonStatic(SimpleName[] fieldNames) {
341         for (int i= 0; i < fieldNames.length; i++) {
342             if (!isStaticFieldName(fieldNames[i]))
343                 return true;
344         }
345         return false;
346     }
347
348     private static boolean containsStatusEntry(final RefactoringStatus status, final RefactoringStatusEntry other) {
349         return status.getEntries(new IRefactoringStatusEntryComparator() {
350
351             public final int compare(final RefactoringStatusEntry entry1, final RefactoringStatusEntry entry2) {
352                 return entry1.getMessage().compareTo(entry2.getMessage());
353             }
354         }, other).length > 0;
355     }
356
357     private static AbstractTypeDeclaration findTypeDeclaration(IType enclosing, AbstractTypeDeclaration[] declarations) {
358         String JavaDoc typeName= enclosing.getElementName();
359         for (int i= 0; i < declarations.length; i++) {
360             AbstractTypeDeclaration declaration= declarations[i];
361             if (declaration.getName().getIdentifier().equals(typeName))
362                 return declaration;
363         }
364         return null;
365     }
366
367     private static AbstractTypeDeclaration findTypeDeclaration(IType type, CompilationUnit unit) {
368         final List JavaDoc types= getDeclaringTypes(type);
369         types.add(type);
370         AbstractTypeDeclaration[] declarations= (AbstractTypeDeclaration[]) unit.types().toArray(new AbstractTypeDeclaration[unit.types().size()]);
371         AbstractTypeDeclaration declaration= null;
372         for (final Iterator JavaDoc iterator= types.iterator(); iterator.hasNext();) {
373             IType enclosing= (IType) iterator.next();
374             declaration= findTypeDeclaration(enclosing, declarations);
375             Assert.isNotNull(declaration);
376             declarations= getAbstractTypeDeclarations(declaration);
377         }
378         Assert.isNotNull(declaration);
379         return declaration;
380     }
381
382     public static AbstractTypeDeclaration[] getAbstractTypeDeclarations(final AbstractTypeDeclaration declaration) {
383         int typeCount= 0;
384         for (Iterator JavaDoc iterator= declaration.bodyDeclarations().listIterator(); iterator.hasNext();) {
385             if (iterator.next() instanceof AbstractTypeDeclaration) {
386                 typeCount++;
387             }
388         }
389         AbstractTypeDeclaration[] declarations= new AbstractTypeDeclaration[typeCount];
390         int next= 0;
391         for (final Iterator JavaDoc iterator= declaration.bodyDeclarations().listIterator(); iterator.hasNext();) {
392             Object JavaDoc object= iterator.next();
393             if (object instanceof AbstractTypeDeclaration) {
394                 declarations[next++]= (AbstractTypeDeclaration) object;
395             }
396         }
397         return declarations;
398     }
399
400     private static ITypeBinding getDeclaringTypeBinding(FieldAccess fieldAccess) {
401         IVariableBinding varBinding= fieldAccess.resolveFieldBinding();
402         if (varBinding == null)
403             return null;
404         return varBinding.getDeclaringClass();
405     }
406
407     private static ITypeBinding getDeclaringTypeBinding(MethodInvocation methodInvocation) {
408         IMethodBinding binding= methodInvocation.resolveMethodBinding();
409         if (binding == null)
410             return null;
411         return binding.getDeclaringClass();
412     }
413
414     // List of ITypes
415
private static List JavaDoc getDeclaringTypes(IType type) {
416         IType declaringType= type.getDeclaringType();
417         if (declaringType == null)
418             return new ArrayList JavaDoc(0);
419         List JavaDoc result= getDeclaringTypes(declaringType);
420         result.add(declaringType);
421         return result;
422     }
423
424     private static String JavaDoc[] getFieldNames(IType type) {
425         try {
426             IField[] fields= type.getFields();
427             List JavaDoc result= new ArrayList JavaDoc(fields.length);
428             for (int i= 0; i < fields.length; i++) {
429                 result.add(fields[i].getElementName());
430             }
431             return (String JavaDoc[]) result.toArray(new String JavaDoc[result.size()]);
432         } catch (JavaModelException e) {
433             return null;
434         }
435     }
436
437     private static Set JavaDoc getMergedSet(Set JavaDoc s1, Set JavaDoc s2) {
438         Set JavaDoc result= new HashSet JavaDoc();
439         result.addAll(s1);
440         result.addAll(s2);
441         return result;
442     }
443
444     private static String JavaDoc[] getParameterNamesOfAllConstructors(IType type) throws JavaModelException {
445         IMethod[] constructors= JavaElementUtil.getAllConstructors(type);
446         Set JavaDoc result= new HashSet JavaDoc();
447         for (int i= 0; i < constructors.length; i++) {
448             result.addAll(Arrays.asList(constructors[i].getParameterNames()));
449         }
450         return (String JavaDoc[]) result.toArray(new String JavaDoc[result.size()]);
451     }
452
453     private static ASTNode[] getReferenceNodesIn(CompilationUnit cuNode, Map JavaDoc references, ICompilationUnit cu) {
454         SearchMatch[] results= (SearchMatch[]) references.get(cu);
455         if (results == null)
456             return new ASTNode[0];
457         return ASTNodeSearchUtil.getAstNodes(results, cuNode);
458     }
459
460     private static boolean isCorrespondingTypeBinding(ITypeBinding binding, IType type) {
461         if (binding == null)
462             return false;
463         return Bindings.getFullyQualifiedName(binding).equals(JavaElementUtil.createSignature(type));
464     }
465
466     private static boolean isStatic(FieldAccess access) {
467         IVariableBinding fieldBinding= access.resolveFieldBinding();
468         if (fieldBinding == null)
469             return false;
470         return JdtFlags.isStatic(fieldBinding);
471     }
472
473     private static boolean isStatic(MethodInvocation invocation) {
474         IMethodBinding methodBinding= invocation.resolveMethodBinding();
475         if (methodBinding == null)
476             return false;
477         return JdtFlags.isStatic(methodBinding);
478     }
479
480     private static boolean isStaticFieldName(SimpleName name) {
481         IBinding binding= name.resolveBinding();
482         if (!(binding instanceof IVariableBinding))
483             return false;
484         IVariableBinding variableBinding= (IVariableBinding) binding;
485         if (!variableBinding.isField())
486             return false;
487         return JdtFlags.isStatic(variableBinding);
488     }
489
490     private TextChangeManager fChangeManager;
491
492     private CodeGenerationSettings fCodeGenerationSettings;
493
494     private boolean fCreateInstanceField;
495
496     private String JavaDoc fEnclosingInstanceFieldName;
497
498     private boolean fIsInstanceFieldCreationMandatory;
499
500     private boolean fIsInstanceFieldCreationPossible;
501
502     private boolean fMarkInstanceFieldAsFinal;
503
504     private String JavaDoc fNameForEnclosingInstanceConstructorParameter;
505
506     private String JavaDoc fNewSourceOfInputType;
507
508     private CompilationUnitRewrite fSourceRewrite;
509
510     private Collection JavaDoc fStaticImports;
511
512     private IType fType;
513
514     private String JavaDoc fQualifiedTypeName;
515
516     private Collection JavaDoc fTypeImports;
517
518     /**
519      * Creates a new move inner to top refactoring.
520      * @param type the type, or <code>null</code> if invoked by scripting
521      * @param settings the code generation settings, or <code>null</code> if invoked by scripting
522      * @throws JavaModelException
523      */

524     public MoveInnerToTopRefactoring(IType type, CodeGenerationSettings settings) throws JavaModelException {
525         fType= type;
526         fCodeGenerationSettings= settings;
527         fMarkInstanceFieldAsFinal= true; // default
528
if (fType != null)
529             initialize();
530     }
531
532     private void initialize() throws JavaModelException {
533         fQualifiedTypeName= JavaModelUtil.concatenateName(fType.getPackageFragment().getElementName(), fType.getElementName());
534         fEnclosingInstanceFieldName= getInitialNameForEnclosingInstanceField();
535         fSourceRewrite= new CompilationUnitRewrite(fType.getCompilationUnit());
536         fIsInstanceFieldCreationPossible= !(JdtFlags.isStatic(fType) || fType.isAnnotation() || fType.isEnum());
537         fIsInstanceFieldCreationMandatory= fIsInstanceFieldCreationPossible && isInstanceFieldCreationMandatory();
538         fCreateInstanceField= fIsInstanceFieldCreationMandatory;
539     }
540
541     private void addEnclosingInstanceDeclaration(final AbstractTypeDeclaration declaration, final ASTRewrite rewrite) throws CoreException {
542         Assert.isNotNull(declaration);
543         Assert.isNotNull(rewrite);
544         final AST ast= declaration.getAST();
545         final VariableDeclarationFragment fragment= ast.newVariableDeclarationFragment();
546         fragment.setName(ast.newSimpleName(fEnclosingInstanceFieldName));
547         final FieldDeclaration newField= ast.newFieldDeclaration(fragment);
548         newField.modifiers().addAll(ASTNodeFactory.newModifiers(ast, getEnclosingInstanceAccessModifiers()));
549         newField.setType(createEnclosingType(ast));
550         final String JavaDoc comment= CodeGeneration.getFieldComment(fType.getCompilationUnit(), declaration.getName().getIdentifier(), fEnclosingInstanceFieldName, StubUtility.getLineDelimiterUsed(fType.getJavaProject()));
551         if (comment != null && comment.length() > 0) {
552             final Javadoc doc= (Javadoc) rewrite.createStringPlaceholder(comment, ASTNode.JAVADOC);
553             newField.setJavadoc(doc);
554         }
555         rewrite.getListRewrite(declaration, declaration.getBodyDeclarationsProperty()).insertFirst(newField, null);
556     }
557
558     private void addEnclosingInstanceTypeParameters(final ITypeBinding[] parameters, final AbstractTypeDeclaration declaration, final ASTRewrite rewrite) {
559         Assert.isNotNull(parameters);
560         Assert.isNotNull(declaration);
561         Assert.isNotNull(rewrite);
562         if (declaration instanceof TypeDeclaration) {
563             final TypeDeclaration type= (TypeDeclaration) declaration;
564             final List JavaDoc existing= type.typeParameters();
565             final Set JavaDoc names= new HashSet JavaDoc();
566             TypeParameter parameter= null;
567             for (final Iterator JavaDoc iterator= existing.iterator(); iterator.hasNext();) {
568                 parameter= (TypeParameter) iterator.next();
569                 names.add(parameter.getName().getIdentifier());
570             }
571             final ListRewrite rewriter= rewrite.getListRewrite(type, TypeDeclaration.TYPE_PARAMETERS_PROPERTY);
572             String JavaDoc name= null;
573             for (int index= 0; index < parameters.length; index++) {
574                 name= parameters[index].getName();
575                 if (!names.contains(name)) {
576                     parameter= type.getAST().newTypeParameter();
577                     parameter.setName(type.getAST().newSimpleName(name));
578                     rewriter.insertLast(parameter, null);
579                 }
580             }
581         }
582     }
583
584     private void addImportsToTargetUnit(final ICompilationUnit targetUnit, final IProgressMonitor monitor) throws CoreException, JavaModelException {
585         monitor.beginTask("", 2); //$NON-NLS-1$
586
try {
587             ImportRewrite rewrite= StubUtility.createImportRewrite(targetUnit, true);
588             if (fTypeImports != null) {
589                 ITypeBinding type= null;
590                 for (final Iterator JavaDoc iterator= fTypeImports.iterator(); iterator.hasNext();) {
591                     type= (ITypeBinding) iterator.next();
592                     rewrite.addImport(type);
593                 }
594             }
595             if (fStaticImports != null) {
596                 IBinding binding= null;
597                 for (final Iterator JavaDoc iterator= fStaticImports.iterator(); iterator.hasNext();) {
598                     binding= (IBinding) iterator.next();
599                     rewrite.addStaticImport(binding);
600                 }
601             }
602             fTypeImports= null;
603             fStaticImports= null;
604             TextEdit edits= rewrite.rewriteImports(new SubProgressMonitor(monitor, 1));
605             JavaModelUtil.applyEdit(targetUnit, edits, false, new SubProgressMonitor(monitor, 1));
606         } finally {
607             monitor.done();
608         }
609     }
610
611     private void addInheritedTypeQualifications(final AbstractTypeDeclaration declaration, final CompilationUnitRewrite targetRewrite, final TextEditGroup group) {
612         Assert.isNotNull(declaration);
613         Assert.isNotNull(targetRewrite);
614         final CompilationUnit unit= (CompilationUnit) declaration.getRoot();
615         final ITypeBinding binding= declaration.resolveBinding();
616         if (binding != null) {
617             Type type= null;
618             if (declaration instanceof TypeDeclaration) {
619                 type= ((TypeDeclaration) declaration).getSuperclassType();
620                 if (type != null && unit.findDeclaringNode(binding) != null)
621                     addTypeQualification(type, targetRewrite, group);
622             }
623             List JavaDoc types= null;
624             if (declaration instanceof TypeDeclaration)
625                 types= ((TypeDeclaration) declaration).superInterfaceTypes();
626             else if (declaration instanceof EnumDeclaration)
627                 types= ((EnumDeclaration) declaration).superInterfaceTypes();
628             if (types != null) {
629                 for (final Iterator JavaDoc iterator= types.iterator(); iterator.hasNext();) {
630                     type= (Type) iterator.next();
631                     if (unit.findDeclaringNode(type.resolveBinding()) != null)
632                         addTypeQualification(type, targetRewrite, group);
633                 }
634             }
635         }
636     }
637
638     private void addParameterToConstructor(final ASTRewrite rewrite, final MethodDeclaration declaration) throws JavaModelException {
639         Assert.isNotNull(rewrite);
640         Assert.isNotNull(declaration);
641         final AST ast= declaration.getAST();
642         final String JavaDoc name= getNameForEnclosingInstanceConstructorParameter();
643         final SingleVariableDeclaration variable= ast.newSingleVariableDeclaration();
644         variable.setType(createEnclosingType(ast));
645         variable.setName(ast.newSimpleName(name));
646         rewrite.getListRewrite(declaration, MethodDeclaration.PARAMETERS_PROPERTY).insertFirst(variable, null);
647         JavadocUtil.addParamJavadoc(name, declaration, rewrite, fType.getJavaProject(), null);
648     }
649
650     private void addSimpleTypeQualification(final CompilationUnitRewrite targetRewrite, final ITypeBinding declaring, final SimpleType simpleType, final TextEditGroup group) {
651         Assert.isNotNull(targetRewrite);
652         Assert.isNotNull(declaring);
653         Assert.isNotNull(simpleType);
654         final AST ast= targetRewrite.getRoot().getAST();
655         if (!(simpleType.getName() instanceof QualifiedName)) {
656             targetRewrite.getASTRewrite().replace(simpleType, ast.newQualifiedType(targetRewrite.getImportRewrite().addImport(declaring, ast), ast.newSimpleName(simpleType.getName().getFullyQualifiedName())), group);
657             targetRewrite.getImportRemover().registerRemovedNode(simpleType);
658         }
659     }
660
661     private void addTypeQualification(final Type type, final CompilationUnitRewrite targetRewrite, final TextEditGroup group) {
662         Assert.isNotNull(type);
663         Assert.isNotNull(targetRewrite);
664         final ITypeBinding binding= type.resolveBinding();
665         if (binding != null) {
666             final ITypeBinding declaring= binding.getDeclaringClass();
667             if (declaring != null) {
668                 if (type instanceof SimpleType) {
669                     final SimpleType simpleType= (SimpleType) type;
670                     addSimpleTypeQualification(targetRewrite, declaring, simpleType, group);
671                 } else if (type instanceof ParameterizedType) {
672                     final ParameterizedType parameterizedType= (ParameterizedType) type;
673                     final Type rawType= parameterizedType.getType();
674                     if (rawType instanceof SimpleType)
675                         addSimpleTypeQualification(targetRewrite, declaring, (SimpleType) rawType, group);
676                 }
677             }
678         }
679     }
680
681     private RefactoringStatus checkConstructorParameterNames() {
682         RefactoringStatus result= new RefactoringStatus();
683         CompilationUnit cuNode= new RefactoringASTParser(AST.JLS3).parse(fType.getCompilationUnit(), false);
684         MethodDeclaration[] nodes= getConstructorDeclarationNodes(findTypeDeclaration(fType, cuNode));
685         for (int i= 0; i < nodes.length; i++) {
686             MethodDeclaration constructor= nodes[i];
687             for (Iterator JavaDoc iter= constructor.parameters().iterator(); iter.hasNext();) {
688                 SingleVariableDeclaration param= (SingleVariableDeclaration) iter.next();
689                 if (fEnclosingInstanceFieldName.equals(param.getName().getIdentifier())) {
690                     String JavaDoc msg= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_name_used, new String JavaDoc[] { param.getName().getIdentifier(), fType.getElementName()});
691                     result.addError(msg, JavaStatusContext.create(fType.getCompilationUnit(), param));
692                 }
693             }
694         }
695         return result;
696     }
697
698     public RefactoringStatus checkEnclosingInstanceName(String JavaDoc name) {
699         if (!fCreateInstanceField)
700             return new RefactoringStatus();
701         RefactoringStatus result= Checks.checkFieldName(name);
702         if (!Checks.startsWithLowerCase(name))
703             result.addWarning(RefactoringCoreMessages.MoveInnerToTopRefactoring_names_start_lowercase);
704
705         if (fType.getField(name).exists()) {
706             Object JavaDoc[] keys= new String JavaDoc[] { name, fType.getElementName()};
707             String JavaDoc msg= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_already_declared, keys);
708             result.addError(msg, JavaStatusContext.create(fType.getField(name)));
709         }
710         return result;
711     }
712
713     public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException {
714         pm.beginTask("", 2);//$NON-NLS-1$
715
try {
716             RefactoringStatus result= new RefactoringStatus();
717
718             if (JdtFlags.isStatic(fType))
719                 result.merge(checkEnclosingInstanceName(fEnclosingInstanceFieldName));
720
721             if (fType.getPackageFragment().getCompilationUnit((JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), fType.getElementName()))).exists()) {
722                 String JavaDoc message= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_compilation_Unit_exists, new String JavaDoc[] { (JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), fType.getElementName())), fType.getPackageFragment().getElementName()});
723                 result.addFatalError(message);
724             }
725             result.merge(checkEnclosingInstanceName(fEnclosingInstanceFieldName));
726             result.merge(Checks.checkCompilationUnitName((JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), fType.getElementName()))));
727             result.merge(checkConstructorParameterNames());
728             result.merge(checkTypeNameInPackage());
729             fChangeManager= createChangeManager(new SubProgressMonitor(pm, 1), result);
730             result.merge(Checks.validateModifiesFiles(ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits()), getValidationContext()));
731             return result;
732         } finally {
733             pm.done();
734         }
735     }
736
737     public RefactoringStatus checkInitialConditions(IProgressMonitor monitor) throws CoreException {
738         return Checks.checkIfCuBroken(fType);
739     }
740
741     private RefactoringStatus checkTypeNameInPackage() throws JavaModelException {
742         IType type= Checks.findTypeInPackage(fType.getPackageFragment(), fType.getElementName());
743         if (type == null || !type.exists())
744             return null;
745         String JavaDoc message= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_type_exists, new String JavaDoc[] { fType.getElementName(), fType.getPackageFragment().getElementName()});
746         return RefactoringStatus.createErrorStatus(message);
747     }
748
749     private Expression createAccessExpressionToEnclosingInstanceFieldText(ASTNode node, IBinding binding, AbstractTypeDeclaration declaration) {
750         if (Modifier.isStatic(binding.getModifiers()))
751             return node.getAST().newName(JavaModelUtil.getTypeQualifiedName(fType.getDeclaringType()));
752         else if ((isInAnonymousTypeInsideInputType(node, declaration) || isInLocalTypeInsideInputType(node, declaration) || isInNonStaticMemberTypeInsideInputType(node, declaration)))
753             return createQualifiedReadAccessExpressionForEnclosingInstance(node.getAST());
754         else
755             return createReadAccessExpressionForEnclosingInstance(node.getAST());
756     }
757
758     public Change createChange(final IProgressMonitor monitor) throws CoreException {
759         monitor.beginTask(RefactoringCoreMessages.MoveInnerToTopRefactoring_creating_change, 1);
760         final Map JavaDoc arguments= new HashMap JavaDoc();
761         String JavaDoc project= null;
762         IJavaProject javaProject= fType.getJavaProject();
763         if (javaProject != null)
764             project= javaProject.getElementName();
765         final String JavaDoc description= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_descriptor_description_short, fType.getElementName());
766         final String JavaDoc header= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_descriptor_description, new String JavaDoc[] { JavaElementLabels.getElementLabel(fType, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(fType.getParent(), JavaElementLabels.ALL_FULLY_QUALIFIED)});
767         final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header);
768         comment.addSetting(Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_original_pattern, JavaElementLabels.getElementLabel(fType, JavaElementLabels.ALL_FULLY_QUALIFIED)));
769         final boolean enclosing= fEnclosingInstanceFieldName != null && !"".equals(fEnclosingInstanceFieldName); //$NON-NLS-1$
770
if (enclosing)
771             comment.addSetting(Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_field_pattern, fEnclosingInstanceFieldName));
772         if (fNameForEnclosingInstanceConstructorParameter != null && !"".equals(fNameForEnclosingInstanceConstructorParameter)) //$NON-NLS-1$
773
comment.addSetting(Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_parameter_pattern, fNameForEnclosingInstanceConstructorParameter));
774         if (enclosing && fMarkInstanceFieldAsFinal)
775             comment.addSetting(RefactoringCoreMessages.MoveInnerToTopRefactoring_declare_final);
776         final JDTRefactoringDescriptor descriptor= new JDTRefactoringDescriptor(IJavaRefactorings.CONVERT_MEMBER_TYPE, project, description, comment.asString(), arguments, RefactoringDescriptor.MULTI_CHANGE | RefactoringDescriptor.STRUCTURAL_CHANGE | JavaRefactoringDescriptor.JAR_REFACTORING | JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT);
777         arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_INPUT, descriptor.elementToHandle(fType));
778         if (enclosing)
779             arguments.put(ATTRIBUTE_FIELD_NAME, fEnclosingInstanceFieldName);
780         if (fNameForEnclosingInstanceConstructorParameter != null && !"".equals(fNameForEnclosingInstanceConstructorParameter)) //$NON-NLS-1$
781
arguments.put(ATTRIBUTE_PARAMETER_NAME, fNameForEnclosingInstanceConstructorParameter);
782         arguments.put(ATTRIBUTE_FIELD, Boolean.valueOf(fCreateInstanceField).toString());
783         arguments.put(ATTRIBUTE_FINAL, Boolean.valueOf(fMarkInstanceFieldAsFinal).toString());
784         arguments.put(ATTRIBUTE_POSSIBLE, Boolean.valueOf(fIsInstanceFieldCreationPossible).toString());
785         arguments.put(ATTRIBUTE_MANDATORY, Boolean.valueOf(fIsInstanceFieldCreationMandatory).toString());
786         final DynamicValidationRefactoringChange result= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.MoveInnerToTopRefactoring_move_to_Top);
787         result.addAll(fChangeManager.getAllChanges());
788         result.add(createCompilationUnitForMovedType(new SubProgressMonitor(monitor, 1)));
789         return result;
790     }
791
792     private TextChangeManager createChangeManager(final IProgressMonitor monitor, final RefactoringStatus status) throws CoreException {
793         Assert.isNotNull(monitor);
794         Assert.isNotNull(status);
795         final TextChangeManager manager= new TextChangeManager();
796         try {
797             monitor.beginTask(RefactoringCoreMessages.MoveInnerToTopRefactoring_creating_preview, 4);
798             final Map JavaDoc rewrites= new HashMap JavaDoc(2);
799             fSourceRewrite.clearASTAndImportRewrites();
800             rewrites.put(fSourceRewrite.getCu(), fSourceRewrite);
801             final MemberVisibilityAdjustor adjustor= new MemberVisibilityAdjustor(fType.getPackageFragment(), fType);
802             adjustor.setRewrites(rewrites);
803             adjustor.setVisibilitySeverity(RefactoringStatus.WARNING);
804             adjustor.setFailureSeverity(RefactoringStatus.WARNING);
805             adjustor.setStatus(status);
806             adjustor.adjustVisibility(new SubProgressMonitor(monitor, 1));
807             final Map JavaDoc parameters= new LinkedHashMap JavaDoc();
808             addTypeParameters(fSourceRewrite.getRoot(), fType, parameters);
809             final ITypeBinding[] bindings= new ITypeBinding[parameters.values().size()];
810             parameters.values().toArray(bindings);
811             final Map JavaDoc typeReferences= createTypeReferencesMapping(new SubProgressMonitor(monitor, 1), status);
812             Map JavaDoc constructorReferences= null;
813             if (JdtFlags.isStatic(fType))
814                 constructorReferences= new HashMap JavaDoc(0);
815             else
816                 constructorReferences= createConstructorReferencesMapping(new SubProgressMonitor(monitor, 1), status);
817             if (fCreateInstanceField) {
818                 // must increase visibility of all member types up
819
// to the top level type to allow this
820
IType type= fType;
821                 ModifierKeyword keyword= null;
822                 while ( (type= type.getDeclaringType()) != null) {
823                     if ((!adjustor.getAdjustments().containsKey(type)) && (Modifier.isPrivate(type.getFlags())))
824                         adjustor.getAdjustments().put(type, new OutgoingMemberVisibilityAdjustment(type, keyword, RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_type_warning, new String JavaDoc[] { MemberVisibilityAdjustor.getLabel(type), MemberVisibilityAdjustor.getLabel(keyword) }), JavaStatusContext.create(type.getCompilationUnit(), type.getSourceRange()))));
825                 }
826             }
827             monitor.worked(1);
828             for (final Iterator JavaDoc iterator= getMergedSet(typeReferences.keySet(), constructorReferences.keySet()).iterator(); iterator.hasNext();) {
829                 final ICompilationUnit unit= (ICompilationUnit) iterator.next();
830                 final CompilationUnitRewrite targetRewrite= getCompilationUnitRewrite(unit);
831                 createCompilationUnitRewrite(bindings, targetRewrite, typeReferences, constructorReferences, adjustor.getAdjustments().containsKey(fType), fType.getCompilationUnit(), unit, false, status, monitor);
832                 if (unit.equals(fType.getCompilationUnit())) {
833                     try {
834                         adjustor.setStatus(new RefactoringStatus());
835                         adjustor.rewriteVisibility(targetRewrite.getCu(), new SubProgressMonitor(monitor, 1));
836                     } finally {
837                         adjustor.setStatus(status);
838                     }
839                     fNewSourceOfInputType= createNewSource(targetRewrite, unit);
840                     targetRewrite.clearASTAndImportRewrites();
841                     createCompilationUnitRewrite(bindings, targetRewrite, typeReferences, constructorReferences, adjustor.getAdjustments().containsKey(fType), fType.getCompilationUnit(), unit, true, status, monitor);
842                 }
843                 adjustor.rewriteVisibility(targetRewrite.getCu(), new SubProgressMonitor(monitor, 1));
844                 manager.manage(unit, targetRewrite.createChange());
845             }
846         } finally {
847             monitor.done();
848         }
849         return manager;
850     }
851
852     private Change createCompilationUnitForMovedType(IProgressMonitor pm) throws CoreException {
853         ICompilationUnit newCuWC= null;
854         try {
855             newCuWC= fType.getPackageFragment().getCompilationUnit(JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), fType.getElementName())).getWorkingCopy(null);
856             String JavaDoc source= createSourceForNewCu(newCuWC, pm);
857             return new CreateCompilationUnitChange(fType.getPackageFragment().getCompilationUnit(JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), fType.getElementName())), source, null);
858         } finally {
859             if (newCuWC != null)
860                 newCuWC.discardWorkingCopy();
861         }
862     }
863
864     private void createCompilationUnitRewrite(final ITypeBinding[] parameters, final CompilationUnitRewrite targetRewrite, final Map JavaDoc typeReferences, final Map JavaDoc constructorReferences, boolean visibilityWasAdjusted, final ICompilationUnit sourceUnit, final ICompilationUnit targetUnit, final boolean remove, final RefactoringStatus status, final IProgressMonitor monitor) throws CoreException {
865         Assert.isNotNull(parameters);
866         Assert.isNotNull(targetRewrite);
867         Assert.isNotNull(typeReferences);
868         Assert.isNotNull(constructorReferences);
869         Assert.isNotNull(sourceUnit);
870         Assert.isNotNull(targetUnit);
871         final CompilationUnit root= targetRewrite.getRoot();
872         final ASTRewrite rewrite= targetRewrite.getASTRewrite();
873         if (targetUnit.equals(sourceUnit)) {
874             final AbstractTypeDeclaration declaration= findTypeDeclaration(fType, root);
875             final TextEditGroup qualifierGroup= fSourceRewrite.createGroupDescription(RefactoringCoreMessages.MoveInnerToTopRefactoring_change_qualifier);
876             ITypeBinding binding= declaration.resolveBinding();
877             if (!remove) {
878                 if (!JdtFlags.isStatic(fType) && fCreateInstanceField) {
879                     if (JavaElementUtil.getAllConstructors(fType).length == 0)
880                         createConstructor(declaration, rewrite);
881                     else
882                         modifyConstructors(declaration, rewrite);
883                     addInheritedTypeQualifications(declaration, targetRewrite, qualifierGroup);
884                     addEnclosingInstanceDeclaration(declaration, rewrite);
885                 }
886                 fTypeImports= new HashSet JavaDoc();
887                 fStaticImports= new HashSet JavaDoc();
888                 ImportRewriteUtil.collectImports(fType.getJavaProject(), declaration, fTypeImports, fStaticImports, false);
889                 if (binding != null)
890                     fTypeImports.remove(binding);
891             }
892             addEnclosingInstanceTypeParameters(parameters, declaration, rewrite);
893             modifyAccessToEnclosingInstance(targetRewrite, declaration, status, monitor);
894             if (binding != null) {
895                 modifyInterfaceMemberModifiers(binding);
896                 final ITypeBinding declaring= binding.getDeclaringClass();
897                 if (declaring != null)
898                     declaration.accept(new TypeReferenceQualifier(binding, null));
899             }
900             final TextEditGroup groupMove= targetRewrite.createGroupDescription(RefactoringCoreMessages.MoveInnerToTopRefactoring_change_label);
901             if (remove) {
902                 rewrite.remove(declaration, groupMove);
903                 targetRewrite.getImportRemover().registerRemovedNode(declaration);
904             } else {
905                 // Bug 101017/96308: Rewrite the visibility of the element to be
906
// moved and add a warning.
907

908                 // Note that this cannot be done in the MemberVisibilityAdjustor, as the private and
909
// static flags must always be cleared when moving to new type.
910
int newFlags= JdtFlags.clearFlag(Modifier.STATIC, declaration.getModifiers());
911                 
912                 if (!visibilityWasAdjusted) {
913                     if (Modifier.isPrivate(declaration.getModifiers()) || Modifier.isProtected(declaration.getModifiers())) {
914                         newFlags= JdtFlags.clearFlag(Modifier.PROTECTED | Modifier.PRIVATE, newFlags);
915                         final RefactoringStatusEntry entry= new RefactoringStatusEntry(RefactoringStatus.WARNING, Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_change_visibility_type_warning, new String JavaDoc[] { BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_FULLY_QUALIFIED)}), JavaStatusContext.create(fSourceRewrite.getCu()));
916                         if (!containsStatusEntry(status, entry))
917                             status.addEntry(entry);
918                     }
919                 }
920
921                 ModifierRewrite.create(rewrite, declaration).setModifiers(newFlags, groupMove);
922             }
923         }
924         ASTNode[] references= getReferenceNodesIn(root, typeReferences, targetUnit);
925         for (int index= 0; index < references.length; index++)
926             updateTypeReference(parameters, references[index], targetRewrite, targetUnit);
927         references= getReferenceNodesIn(root, constructorReferences, targetUnit);
928         for (int index= 0; index < references.length; index++)
929             updateConstructorReference(parameters, references[index], targetRewrite, targetUnit);
930     }
931
932     private void createConstructor(final AbstractTypeDeclaration declaration, final ASTRewrite rewrite) throws CoreException {
933         Assert.isNotNull(declaration);
934         Assert.isNotNull(rewrite);
935         final AST ast= declaration.getAST();
936         final MethodDeclaration constructor= ast.newMethodDeclaration();
937         constructor.setConstructor(true);
938         constructor.setName(ast.newSimpleName(declaration.getName().getIdentifier()));
939         final String JavaDoc comment= CodeGeneration.getMethodComment(fType.getCompilationUnit(), fType.getElementName(), fType.getElementName(), getNewConstructorParameterNames(), new String JavaDoc[0], null, null, StubUtility.getLineDelimiterUsed(fType.getJavaProject()));
940         if (comment != null && comment.length() > 0) {
941             final Javadoc doc= (Javadoc) rewrite.createStringPlaceholder(comment, ASTNode.JAVADOC);
942             constructor.setJavadoc(doc);
943         }
944         if (fCreateInstanceField) {
945             final SingleVariableDeclaration variable= ast.newSingleVariableDeclaration();
946             final String JavaDoc name= getNameForEnclosingInstanceConstructorParameter();
947             variable.setName(ast.newSimpleName(name));
948             variable.setType(createEnclosingType(ast));
949             constructor.parameters().add(variable);
950             final Block body= ast.newBlock();
951             final Assignment assignment= ast.newAssignment();
952             if (fCodeGenerationSettings.useKeywordThis || fEnclosingInstanceFieldName.equals(fNameForEnclosingInstanceConstructorParameter)) {
953                 final FieldAccess access= ast.newFieldAccess();
954                 access.setExpression(ast.newThisExpression());
955                 access.setName(ast.newSimpleName(fEnclosingInstanceFieldName));
956                 assignment.setLeftHandSide(access);
957             } else
958                 assignment.setLeftHandSide(ast.newSimpleName(fEnclosingInstanceFieldName));
959             assignment.setRightHandSide(ast.newSimpleName(name));
960             final Statement statement= ast.newExpressionStatement(assignment);
961             body.statements().add(statement);
962             constructor.setBody(body);
963         } else
964             constructor.setBody(ast.newBlock());
965         rewrite.getListRewrite(declaration, declaration.getBodyDeclarationsProperty()).insertFirst(constructor, null);
966     }
967
968     // Map<ICompilationUnit, SearchMatch[]>
969
private Map JavaDoc createConstructorReferencesMapping(IProgressMonitor pm, RefactoringStatus status) throws JavaModelException {
970         SearchResultGroup[] groups= ConstructorReferenceFinder.getConstructorReferences(fType, pm, status);
971         Map JavaDoc result= new HashMap JavaDoc();
972         for (int i= 0; i < groups.length; i++) {
973             SearchResultGroup group= groups[i];
974             ICompilationUnit cu= group.getCompilationUnit();
975             if (cu == null)
976                 continue;
977             result.put(cu, group.getSearchResults());
978         }
979         return result;
980     }
981
982     private Expression createEnclosingInstanceCreationString(final ASTNode node, final ICompilationUnit cu) throws JavaModelException {
983         Assert.isTrue((node instanceof ClassInstanceCreation) || (node instanceof SuperConstructorInvocation));
984         Assert.isNotNull(cu);
985         Expression expression= null;
986         if (node instanceof ClassInstanceCreation)
987             expression= ((ClassInstanceCreation) node).getExpression();
988         else
989             expression= ((SuperConstructorInvocation) node).getExpression();
990         final AST ast= node.getAST();
991         if (expression != null)
992             return expression;
993         else if (JdtFlags.isStatic(fType))
994             return null;
995         else if (isInsideSubclassOfDeclaringType(node))
996             return ast.newThisExpression();
997         else if ((node.getStartPosition() >= fType.getSourceRange().getOffset() && ASTNodes.getExclusiveEnd(node) <= fType.getSourceRange().getOffset() + fType.getSourceRange().getLength())) {
998             if (fCodeGenerationSettings.useKeywordThis || fEnclosingInstanceFieldName.equals(fNameForEnclosingInstanceConstructorParameter)) {
999                 final FieldAccess access= ast.newFieldAccess();
1000                access.setExpression(ast.newThisExpression());
1001                access.setName(ast.newSimpleName(fEnclosingInstanceFieldName));
1002                return access;
1003            } else
1004                return ast.newSimpleName(fEnclosingInstanceFieldName);
1005        } else if (isInsideTypeNestedInDeclaringType(node)) {
1006            final ThisExpression qualified= ast.newThisExpression();
1007            qualified.setQualifier(ast.newSimpleName(fType.getDeclaringType().getElementName()));
1008            return qualified;
1009        }
1010        return null;
1011    }
1012
1013    private Type createEnclosingType(final AST ast) throws JavaModelException {
1014        Assert.isNotNull(ast);
1015        final ITypeParameter[] parameters= fType.getDeclaringType().getTypeParameters();
1016        final Type type= ASTNodeFactory.newType(ast, JavaModelUtil.getTypeQualifiedName(fType.getDeclaringType()));
1017        if (parameters.length > 0) {
1018            final ParameterizedType parameterized= ast.newParameterizedType(type);
1019            for (int index= 0; index < parameters.length; index++)
1020                parameterized.typeArguments().add(ast.newSimpleType(ast.newSimpleName(parameters[index].getElementName())));
1021            return parameterized;
1022        }
1023        return type;
1024    }
1025
1026    private String JavaDoc createNewSource(final CompilationUnitRewrite targetRewrite, final ICompilationUnit unit) throws CoreException, JavaModelException {
1027        Assert.isNotNull(targetRewrite);
1028        Assert.isNotNull(unit);
1029        TextChange change= targetRewrite.createChange();
1030        if (change == null)
1031            change= new CompilationUnitChange("", unit); //$NON-NLS-1$
1032
final String JavaDoc source= change.getPreviewContent(new NullProgressMonitor());
1033        final ASTParser parser= ASTParser.newParser(AST.JLS3);
1034        parser.setProject(fType.getJavaProject());
1035        parser.setResolveBindings(false);
1036        parser.setSource(source.toCharArray());
1037        final AbstractTypeDeclaration declaration= findTypeDeclaration(fType, (CompilationUnit) parser.createAST(null));
1038        return source.substring(declaration.getStartPosition(), ASTNodes.getExclusiveEnd(declaration));
1039    }
1040
1041    private Expression createQualifiedReadAccessExpressionForEnclosingInstance(AST ast) {
1042        ThisExpression expression= ast.newThisExpression();
1043        expression.setQualifier(ast.newName(new String JavaDoc[] { fType.getElementName()}));
1044        FieldAccess access= ast.newFieldAccess();
1045        access.setExpression(expression);
1046        access.setName(ast.newSimpleName(fEnclosingInstanceFieldName));
1047        return access;
1048    }
1049
1050    private Expression createReadAccessExpressionForEnclosingInstance(AST ast) {
1051        if (fCodeGenerationSettings.useKeywordThis || fEnclosingInstanceFieldName.equals(fNameForEnclosingInstanceConstructorParameter)) {
1052            final FieldAccess access= ast.newFieldAccess();
1053            access.setExpression(ast.newThisExpression());
1054            access.setName(ast.newSimpleName(fEnclosingInstanceFieldName));
1055            return access;
1056        }
1057        return ast.newSimpleName(fEnclosingInstanceFieldName);
1058    }
1059
1060    private String JavaDoc createSourceForNewCu(final ICompilationUnit unit, final IProgressMonitor monitor) throws CoreException {
1061        Assert.isNotNull(unit);
1062        Assert.isNotNull(monitor);
1063        try {
1064            monitor.beginTask("", 2); //$NON-NLS-1$
1065
final String JavaDoc separator= StubUtility.getLineDelimiterUsed(fType.getJavaProject());
1066            final String JavaDoc block= getAlignedSourceBlock(unit, fNewSourceOfInputType);
1067            String JavaDoc content= CodeGeneration.getCompilationUnitContent(unit, null, block, separator);
1068            if (content == null || block.startsWith("/*") || block.startsWith("//")) { //$NON-NLS-1$//$NON-NLS-2$
1069
final StringBuffer JavaDoc buffer= new StringBuffer JavaDoc();
1070                if (!fType.getPackageFragment().isDefaultPackage()) {
1071                    buffer.append("package ").append(fType.getPackageFragment().getElementName()).append(';'); //$NON-NLS-1$
1072
}
1073                buffer.append(separator).append(separator);
1074                buffer.append(block);
1075                content= buffer.toString();
1076            }
1077            unit.getBuffer().setContents(content);
1078            addImportsToTargetUnit(unit, new SubProgressMonitor(monitor, 1));
1079        } finally {
1080            monitor.done();
1081        }
1082        return unit.getSource();
1083    }
1084
1085    // Map<ICompilationUnit, SearchMatch[]>
1086
private Map JavaDoc createTypeReferencesMapping(IProgressMonitor pm, RefactoringStatus status) throws JavaModelException {
1087        final RefactoringSearchEngine2 engine= new RefactoringSearchEngine2(SearchPattern.createPattern(fType, IJavaSearchConstants.ALL_OCCURRENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE));
1088        engine.setFiltering(true, true);
1089        engine.setScope(RefactoringScopeFactory.create(fType));
1090        engine.setStatus(status);
1091        engine.searchPattern(new SubProgressMonitor(pm, 1));
1092        final SearchResultGroup[] groups= (SearchResultGroup[]) engine.getResults();
1093        Map JavaDoc result= new HashMap JavaDoc();
1094        for (int i= 0; i < groups.length; i++) {
1095            SearchResultGroup group= groups[i];
1096            ICompilationUnit cu= group.getCompilationUnit();
1097            if (cu == null)
1098                continue;
1099            result.put(cu, group.getSearchResults());
1100        }
1101        return result;
1102    }
1103
1104    private String JavaDoc getAlignedSourceBlock(final ICompilationUnit unit, final String JavaDoc block) {
1105        Assert.isNotNull(block);
1106        final String JavaDoc[] lines= Strings.convertIntoLines(block);
1107        Strings.trimIndentation(lines, unit.getJavaProject(), false);
1108        return Strings.concatenate(lines, StubUtility.getLineDelimiterUsed(fType.getJavaProject()));
1109    }
1110
1111    private CompilationUnitRewrite getCompilationUnitRewrite(final ICompilationUnit unit) {
1112        Assert.isNotNull(unit);
1113        if (unit.equals(fType.getCompilationUnit()))
1114            return fSourceRewrite;
1115        return new CompilationUnitRewrite(unit);
1116    }
1117
1118    private MethodDeclaration[] getConstructorDeclarationNodes(final AbstractTypeDeclaration declaration) {
1119        if (declaration instanceof TypeDeclaration) {
1120            final MethodDeclaration[] declarations= ((TypeDeclaration) declaration).getMethods();
1121            final List JavaDoc result= new ArrayList JavaDoc(2);
1122            for (int index= 0; index < declarations.length; index++) {
1123                if (declarations[index].isConstructor())
1124                    result.add(declarations[index]);
1125            }
1126            return (MethodDeclaration[]) result.toArray(new MethodDeclaration[result.size()]);
1127        }
1128        return new MethodDeclaration[] {};
1129    }
1130
1131    public boolean getCreateInstanceField() {
1132        return fCreateInstanceField;
1133    }
1134
1135    private int getEnclosingInstanceAccessModifiers() {
1136        if (fMarkInstanceFieldAsFinal)
1137            return Modifier.PRIVATE | Modifier.FINAL;
1138        else
1139            return Modifier.PRIVATE;
1140    }
1141
1142    public String JavaDoc getEnclosingInstanceName() {
1143        return fEnclosingInstanceFieldName;
1144    }
1145
1146    private String JavaDoc getInitialNameForEnclosingInstanceField() {
1147        IType enclosingType= fType.getDeclaringType();
1148        if (enclosingType == null)
1149            return ""; //$NON-NLS-1$
1150
String JavaDoc[] suggestedNames= StubUtility.getFieldNameSuggestions(fType.getDeclaringType(), getEnclosingInstanceAccessModifiers(), getFieldNames(fType));
1151        if (suggestedNames.length > 0)
1152            return suggestedNames[0];
1153        String JavaDoc name= enclosingType.getElementName();
1154        if (name.equals("")) //$NON-NLS-1$
1155
return ""; //$NON-NLS-1$
1156
return Character.toLowerCase(name.charAt(0)) + name.substring(1);
1157    }
1158
1159    public IType getInputType() {
1160        return fType;
1161    }
1162
1163    /*
1164     * @see org.eclipse.jdt.internal.corext.refactoring.base.IRefactoring#getName()
1165     */

1166    public String JavaDoc getName() {
1167        return RefactoringCoreMessages.MoveInnerToTopRefactoring_name;
1168    }
1169
1170    private String JavaDoc getNameForEnclosingInstanceConstructorParameter() throws JavaModelException {
1171        if (fNameForEnclosingInstanceConstructorParameter != null)
1172            return fNameForEnclosingInstanceConstructorParameter;
1173
1174        String JavaDoc[] suggestedNames= StubUtility.getArgumentNameSuggestions(fType.getDeclaringType(), getParameterNamesOfAllConstructors(fType));
1175        if (suggestedNames.length > 0)
1176            fNameForEnclosingInstanceConstructorParameter= suggestedNames[0];
1177        else
1178            fNameForEnclosingInstanceConstructorParameter= fEnclosingInstanceFieldName;
1179        return fNameForEnclosingInstanceConstructorParameter;
1180    }
1181
1182    private String JavaDoc[] getNewConstructorParameterNames() throws JavaModelException {
1183        if (!fCreateInstanceField)
1184            return new String JavaDoc[0];
1185        return new String JavaDoc[] { getNameForEnclosingInstanceConstructorParameter()};
1186    }
1187
1188    private ASTNode getNewQualifiedNameNode(ITypeBinding[] parameters, Name name) {
1189        final AST ast= name.getAST();
1190        boolean raw= false;
1191        final ITypeBinding binding= name.resolveTypeBinding();
1192        if (binding != null && binding.isRawType())
1193            raw= true;
1194        if (parameters != null && parameters.length > 0 && !raw) {
1195            final ParameterizedType type= ast.newParameterizedType(ast.newSimpleType(ast.newName(fQualifiedTypeName)));
1196            for (int index= 0; index < parameters.length; index++)
1197                type.typeArguments().add(ast.newSimpleType(ast.newSimpleName(parameters[index].getName())));
1198            return type;
1199        }
1200        return ast.newName(fQualifiedTypeName);
1201    }
1202
1203    private ASTNode getNewUnqualifiedTypeNode(ITypeBinding[] parameters, Name name) {
1204        final AST ast= name.getAST();
1205        boolean raw= false;
1206        final ITypeBinding binding= name.resolveTypeBinding();
1207        if (binding != null && binding.isRawType())
1208            raw= true;
1209        if (parameters != null && parameters.length > 0 && !raw) {
1210            final ParameterizedType type= ast.newParameterizedType(ast.newSimpleType(ast.newSimpleName(fType.getElementName())));
1211            for (int index= 0; index < parameters.length; index++)
1212                type.typeArguments().add(ast.newSimpleType(ast.newSimpleName(parameters[index].getName())));
1213            return type;
1214        }
1215        return ast.newSimpleType(ast.newSimpleName(fType.getElementName()));
1216    }
1217
1218    private boolean insertExpressionAsParameter(ClassInstanceCreation cic, ASTRewrite rewrite, ICompilationUnit cu, TextEditGroup group) throws JavaModelException {
1219        final Expression expression= createEnclosingInstanceCreationString(cic, cu);
1220        if (expression == null)
1221            return false;
1222        rewrite.getListRewrite(cic, ClassInstanceCreation.ARGUMENTS_PROPERTY).insertFirst(expression, group);
1223        return true;
1224    }
1225
1226    private boolean insertExpressionAsParameter(SuperConstructorInvocation sci, ASTRewrite rewrite, ICompilationUnit cu, TextEditGroup group) throws JavaModelException {
1227        final Expression expression= createEnclosingInstanceCreationString(sci, cu);
1228        if (expression == null)
1229            return false;
1230        rewrite.getListRewrite(sci, SuperConstructorInvocation.ARGUMENTS_PROPERTY).insertFirst(expression, group);
1231        return true;
1232    }
1233
1234    public boolean isCreatingInstanceFieldMandatory() {
1235        return fIsInstanceFieldCreationMandatory;
1236    }
1237
1238    public boolean isCreatingInstanceFieldPossible() {
1239        return fIsInstanceFieldCreationPossible;
1240    }
1241
1242    private boolean isInAnonymousTypeInsideInputType(ASTNode node, AbstractTypeDeclaration declaration) {
1243        final AnonymousClassDeclaration anonymous= (AnonymousClassDeclaration) ASTNodes.getParent(node, AnonymousClassDeclaration.class);
1244        return anonymous != null && ASTNodes.isParent(anonymous, declaration);
1245    }
1246
1247    private boolean isInLocalTypeInsideInputType(ASTNode node, AbstractTypeDeclaration declaration) {
1248        final TypeDeclarationStatement statement= (TypeDeclarationStatement) ASTNodes.getParent(node, TypeDeclarationStatement.class);
1249        return statement != null && ASTNodes.isParent(statement, declaration);
1250    }
1251
1252    private boolean isInNonStaticMemberTypeInsideInputType(ASTNode node, AbstractTypeDeclaration declaration) {
1253        final AbstractTypeDeclaration nested= (AbstractTypeDeclaration) ASTNodes.getParent(node, AbstractTypeDeclaration.class);
1254        return nested != null && !declaration.equals(nested) && !Modifier.isStatic(nested.getFlags()) && ASTNodes.isParent(nested, declaration);
1255    }
1256
1257    private boolean isInsideSubclassOfDeclaringType(ASTNode node) {
1258        Assert.isTrue((node instanceof ClassInstanceCreation) || (node instanceof SuperConstructorInvocation));
1259        final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) ASTNodes.getParent(node, AbstractTypeDeclaration.class);
1260        Assert.isNotNull(declaration);
1261
1262        final AnonymousClassDeclaration anonymous= (AnonymousClassDeclaration) ASTNodes.getParent(node, AnonymousClassDeclaration.class);
1263        boolean isAnonymous= anonymous != null && ASTNodes.isParent(anonymous, declaration);
1264        if (isAnonymous)
1265            return anonymous != null && isSubclassBindingOfEnclosingType(anonymous.resolveBinding());
1266        return isSubclassBindingOfEnclosingType(declaration.resolveBinding());
1267    }
1268
1269    private boolean isInsideTypeNestedInDeclaringType(ASTNode node) {
1270        Assert.isTrue((node instanceof ClassInstanceCreation) || (node instanceof SuperConstructorInvocation));
1271        final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) ASTNodes.getParent(node, AbstractTypeDeclaration.class);
1272        Assert.isNotNull(declaration);
1273        ITypeBinding enclosing= declaration.resolveBinding();
1274        while (enclosing != null) {
1275            if (isCorrespondingTypeBinding(enclosing, fType.getDeclaringType()))
1276                return true;
1277            enclosing= enclosing.getDeclaringClass();
1278        }
1279        return false;
1280    }
1281
1282    private boolean isInstanceFieldCreationMandatory() throws JavaModelException {
1283        final MemberAccessNodeCollector collector= new MemberAccessNodeCollector(fType.getDeclaringType().newSupertypeHierarchy(new NullProgressMonitor()));
1284        findTypeDeclaration(fType, fSourceRewrite.getRoot()).accept(collector);
1285        return containsNonStatic(collector.getFieldAccesses()) || containsNonStatic(collector.getMethodInvocations()) || containsNonStatic(collector.getSimpleFieldNames());
1286    }
1287
1288    public boolean isInstanceFieldMarkedFinal() {
1289        return fMarkInstanceFieldAsFinal;
1290    }
1291
1292    private boolean isSubclassBindingOfEnclosingType(ITypeBinding binding) {
1293        while (binding != null) {
1294            if (isCorrespondingTypeBinding(binding, fType.getDeclaringType()))
1295                return true;
1296            binding= binding.getSuperclass();
1297        }
1298        return false;
1299    }
1300
1301    /*
1302     * This method qualifies accesses from within the moved type to the (now former) enclosed
1303     * type of the moved type. Note that all visibility changes have already been scheduled
1304     * in the visibility adjustor.
1305     */

1306    private void modifyAccessToEnclosingInstance(final CompilationUnitRewrite targetRewrite, final AbstractTypeDeclaration declaration, final RefactoringStatus status, final IProgressMonitor monitor) throws JavaModelException {
1307        Assert.isNotNull(targetRewrite);
1308        Assert.isNotNull(declaration);
1309        Assert.isNotNull(monitor);
1310        final Set JavaDoc handledMethods= new HashSet JavaDoc();
1311        final Set JavaDoc handledFields= new HashSet JavaDoc();
1312        final MemberAccessNodeCollector collector= new MemberAccessNodeCollector(fType.getDeclaringType().newSupertypeHierarchy(new SubProgressMonitor(monitor, 1)));
1313        declaration.accept(collector);
1314        modifyAccessToMethodsFromEnclosingInstance(targetRewrite, handledMethods, collector.getMethodInvocations(), declaration, status);
1315        modifyAccessToFieldsFromEnclosingInstance(targetRewrite, handledFields, collector.getFieldAccesses(), declaration, status);
1316        modifyAccessToFieldsFromEnclosingInstance(targetRewrite, handledFields, collector.getSimpleFieldNames(), declaration, status);
1317    }
1318
1319    private void modifyAccessToFieldsFromEnclosingInstance(CompilationUnitRewrite targetRewrite, Set JavaDoc handledFields, FieldAccess[] fieldAccesses, AbstractTypeDeclaration declaration, RefactoringStatus status) {
1320        FieldAccess access= null;
1321        for (int index= 0; index < fieldAccesses.length; index++) {
1322            access= fieldAccesses[index];
1323            Assert.isNotNull(access.getExpression());
1324            if (!(access.getExpression() instanceof ThisExpression) || (!(((ThisExpression) access.getExpression()).getQualifier() != null)))
1325                continue;
1326
1327            final IVariableBinding binding= access.resolveFieldBinding();
1328            if (binding != null) {
1329                targetRewrite.getASTRewrite().replace(access.getExpression(), createAccessExpressionToEnclosingInstanceFieldText(access, binding, declaration), null);
1330                targetRewrite.getImportRemover().registerRemovedNode(access.getExpression());
1331            }
1332        }
1333    }
1334
1335    private void modifyAccessToFieldsFromEnclosingInstance(CompilationUnitRewrite targetRewrite, Set JavaDoc handledFields, SimpleName[] simpleNames, AbstractTypeDeclaration declaration, RefactoringStatus status) {
1336        IBinding binding= null;
1337        SimpleName simpleName= null;
1338        IVariableBinding variable= null;
1339        for (int index= 0; index < simpleNames.length; index++) {
1340            simpleName= simpleNames[index];
1341            binding= simpleName.resolveBinding();
1342            if (binding != null && binding instanceof IVariableBinding && !(simpleName.getParent() instanceof FieldAccess)) {
1343                variable= (IVariableBinding) binding;
1344                final FieldAccess access= simpleName.getAST().newFieldAccess();
1345                access.setExpression(createAccessExpressionToEnclosingInstanceFieldText(simpleName, variable, declaration));
1346                access.setName(simpleName.getAST().newSimpleName(simpleName.getIdentifier()));
1347                targetRewrite.getASTRewrite().replace(simpleName, access, null);
1348                targetRewrite.getImportRemover().registerRemovedNode(simpleName);
1349            }
1350        }
1351    }
1352
1353    private void modifyAccessToMethodsFromEnclosingInstance(CompilationUnitRewrite targetRewrite, Set JavaDoc handledMethods, MethodInvocation[] methodInvocations, AbstractTypeDeclaration declaration, RefactoringStatus status) {
1354        IMethodBinding binding= null;
1355        MethodInvocation invocation= null;
1356        for (int index= 0; index < methodInvocations.length; index++) {
1357            invocation= methodInvocations[index];
1358            binding= invocation.resolveMethodBinding();
1359            if (binding != null) {
1360                final Expression target= invocation.getExpression();
1361                if (target == null) {
1362                    final Expression expression= createAccessExpressionToEnclosingInstanceFieldText(invocation, binding, declaration);
1363                    targetRewrite.getASTRewrite().set(invocation, MethodInvocation.EXPRESSION_PROPERTY, expression, null);
1364                } else {
1365                    if (!(invocation.getExpression() instanceof ThisExpression) || !(((ThisExpression) invocation.getExpression()).getQualifier() != null))
1366                        continue;
1367                    targetRewrite.getASTRewrite().replace(target, createAccessExpressionToEnclosingInstanceFieldText(invocation, binding, declaration), null);
1368                    targetRewrite.getImportRemover().registerRemovedNode(target);
1369                }
1370            }
1371        }
1372    }
1373
1374    private void modifyConstructors(AbstractTypeDeclaration declaration, ASTRewrite rewrite) throws CoreException {
1375        final MethodDeclaration[] declarations= getConstructorDeclarationNodes(declaration);
1376        for (int index= 0; index < declarations.length; index++) {
1377            Assert.isTrue(declarations[index].isConstructor());
1378            addParameterToConstructor(rewrite, declarations[index]);
1379            setEnclosingInstanceFieldInConstructor(rewrite, declarations[index]);
1380        }
1381    }
1382    
1383    private void modifyInterfaceMemberModifiers(final ITypeBinding binding) {
1384        Assert.isNotNull(binding);
1385        ITypeBinding declaring= binding.getDeclaringClass();
1386        while (declaring != null && !declaring.isInterface()) {
1387            declaring= declaring.getDeclaringClass();
1388        }
1389        if (declaring != null) {
1390            final ASTNode node= ASTNodes.findDeclaration(binding, fSourceRewrite.getRoot());
1391            if (node instanceof AbstractTypeDeclaration) {
1392                ModifierRewrite.create(fSourceRewrite.getASTRewrite(), node).setVisibility(Modifier.PUBLIC, null);
1393            }
1394        }
1395    }
1396
1397    public void setCreateInstanceField(boolean create) {
1398        Assert.isTrue(fIsInstanceFieldCreationPossible);
1399        Assert.isTrue(!fIsInstanceFieldCreationMandatory);
1400        fCreateInstanceField= create;
1401    }
1402
1403    private void setEnclosingInstanceFieldInConstructor(ASTRewrite rewrite, MethodDeclaration decl) throws JavaModelException {
1404        final AST ast= decl.getAST();
1405        final Block body= decl.getBody();
1406        final List JavaDoc statements= body.statements();
1407        if (statements.isEmpty()) {
1408            final Assignment assignment= ast.newAssignment();
1409            assignment.setLeftHandSide(createReadAccessExpressionForEnclosingInstance(ast));
1410            assignment.setRightHandSide(ast.newSimpleName(getNameForEnclosingInstanceConstructorParameter()));
1411            rewrite.getListRewrite(body, Block.STATEMENTS_PROPERTY).insertFirst(ast.newExpressionStatement(assignment), null);
1412        } else {
1413            final Statement first= (Statement) statements.get(0);
1414            if (first instanceof ConstructorInvocation) {
1415                rewrite.getListRewrite(first, ConstructorInvocation.ARGUMENTS_PROPERTY).insertFirst(ast.newSimpleName(fEnclosingInstanceFieldName), null);
1416            } else {
1417                int index= 0;
1418                if (first instanceof SuperConstructorInvocation)
1419                    index++;
1420                final Assignment assignment= ast.newAssignment();
1421                assignment.setLeftHandSide(createReadAccessExpressionForEnclosingInstance(ast));
1422                assignment.setRightHandSide(ast.newSimpleName(getNameForEnclosingInstanceConstructorParameter()));
1423                rewrite.getListRewrite(body, Block.STATEMENTS_PROPERTY).insertAt(ast.newExpressionStatement(assignment), index, null);
1424            }
1425        }
1426    }
1427
1428    public void setEnclosingInstanceName(String JavaDoc name) {
1429        Assert.isNotNull(name);
1430        fEnclosingInstanceFieldName= name;
1431    }
1432
1433    public void setMarkInstanceFieldAsFinal(boolean mark) {
1434        fMarkInstanceFieldAsFinal= mark;
1435    }
1436
1437    private void updateConstructorReference(final ClassInstanceCreation creation, final CompilationUnitRewrite targetRewrite, final ICompilationUnit unit, TextEditGroup group) throws JavaModelException {
1438        Assert.isNotNull(creation);
1439        Assert.isNotNull(targetRewrite);
1440        Assert.isNotNull(unit);
1441        final ASTRewrite rewrite= targetRewrite.getASTRewrite();
1442        if (fCreateInstanceField)
1443            insertExpressionAsParameter(creation, rewrite, unit, group);
1444        final Expression expression= creation.getExpression();
1445        if (expression != null) {
1446            rewrite.remove(expression, null);
1447            targetRewrite.getImportRemover().registerRemovedNode(expression);
1448        }
1449    }
1450
1451    private void updateConstructorReference(ITypeBinding[] parameters, ASTNode reference, CompilationUnitRewrite targetRewrite, ICompilationUnit cu) throws CoreException {
1452        final TextEditGroup group= targetRewrite.createGroupDescription(RefactoringCoreMessages.MoveInnerToTopRefactoring_update_constructor_reference);
1453        if (reference instanceof SuperConstructorInvocation)
1454            updateConstructorReference((SuperConstructorInvocation) reference, targetRewrite, cu, group);
1455        else if (reference instanceof ClassInstanceCreation)
1456            updateConstructorReference((ClassInstanceCreation) reference, targetRewrite, cu, group);
1457        else if (reference.getParent() instanceof ClassInstanceCreation)
1458            updateConstructorReference((ClassInstanceCreation) reference.getParent(), targetRewrite, cu, group);
1459        else if (reference.getParent() instanceof ParameterizedType && reference.getParent().getParent() instanceof ClassInstanceCreation)
1460            updateConstructorReference(parameters, (ParameterizedType) reference.getParent(), targetRewrite, cu, group);
1461    }
1462
1463    private void updateConstructorReference(ITypeBinding[] parameters, ParameterizedType type, CompilationUnitRewrite targetRewrite, ICompilationUnit cu, TextEditGroup group) throws CoreException {
1464        final ListRewrite rewrite= targetRewrite.getASTRewrite().getListRewrite(type, ParameterizedType.TYPE_ARGUMENTS_PROPERTY);
1465        TypeParameter parameter= null;
1466        for (int index= type.typeArguments().size(); index < parameters.length; index++) {
1467            parameter= targetRewrite.getRoot().getAST().newTypeParameter();
1468            parameter.setName(targetRewrite.getRoot().getAST().newSimpleName(parameters[index].getName()));
1469            rewrite.insertLast(parameter, group);
1470        }
1471        if (type.getParent() instanceof ClassInstanceCreation)
1472            updateConstructorReference((ClassInstanceCreation) type.getParent(), targetRewrite, cu, group);
1473    }
1474
1475    private void updateConstructorReference(final SuperConstructorInvocation invocation, final CompilationUnitRewrite targetRewrite, final ICompilationUnit unit, TextEditGroup group) throws CoreException {
1476        Assert.isNotNull(invocation);
1477        Assert.isNotNull(targetRewrite);
1478        Assert.isNotNull(unit);
1479        final ASTRewrite rewrite= targetRewrite.getASTRewrite();
1480        if (fCreateInstanceField)
1481            insertExpressionAsParameter(invocation, rewrite, unit, group);
1482        final Expression expression= invocation.getExpression();
1483        if (expression != null) {
1484            rewrite.remove(expression, null);
1485            targetRewrite.getImportRemover().registerRemovedNode(expression);
1486        }
1487    }
1488
1489    private boolean updateNameReference(ITypeBinding[] parameters, Name name, CompilationUnitRewrite targetRewrite, TextEditGroup group) {
1490        if (ASTNodes.asString(name).equals(fType.getFullyQualifiedName('.'))) {
1491            targetRewrite.getASTRewrite().replace(name, getNewQualifiedNameNode(parameters, name), group);
1492            targetRewrite.getImportRemover().registerRemovedNode(name);
1493            return true;
1494        }
1495        targetRewrite.getASTRewrite().replace(name, getNewUnqualifiedTypeNode(parameters, name), group);
1496        targetRewrite.getImportRemover().registerRemovedNode(name);
1497        return true;
1498    }
1499
1500    private boolean updateParameterizedTypeReference(ITypeBinding[] parameters, ParameterizedType type, CompilationUnitRewrite targetRewrite, TextEditGroup group) {
1501        if (!(type.getParent() instanceof ClassInstanceCreation)) {
1502            final ListRewrite rewrite= targetRewrite.getASTRewrite().getListRewrite(type, ParameterizedType.TYPE_ARGUMENTS_PROPERTY);
1503            final AST ast= targetRewrite.getRoot().getAST();
1504            Type simpleType= null;
1505            for (int index= type.typeArguments().size(); index < parameters.length; index++) {
1506                simpleType= ast.newSimpleType(ast.newSimpleName(parameters[index].getName()));
1507                rewrite.insertLast(simpleType, group);
1508            }
1509        }
1510        return true;
1511    }
1512
1513    private boolean updateReference(ITypeBinding[] parameters, ASTNode node, CompilationUnitRewrite rewrite, TextEditGroup group) {
1514        if (node.getLocationInParent() == ParameterizedType.TYPE_PROPERTY) {
1515            updateParameterizedTypeReference(parameters, (ParameterizedType) node.getParent(), rewrite, group);
1516            return updateNameReference(new ITypeBinding[] {}, ((SimpleType) node).getName(), rewrite, group);
1517        } else if (node instanceof QualifiedName)
1518            return updateNameReference(parameters, (QualifiedName) node, rewrite, group);
1519        else if (node instanceof SimpleType)
1520            return updateNameReference(parameters, ((SimpleType) node).getName(), rewrite, group);
1521        else
1522            return false;
1523    }
1524
1525    private void updateReferenceInImport(ImportDeclaration enclosingImport, ASTNode node, CompilationUnitRewrite rewrite) throws CoreException {
1526        final IBinding binding= enclosingImport.resolveBinding();
1527        if (binding instanceof ITypeBinding) {
1528            final ITypeBinding type= (ITypeBinding) binding;
1529            final ImportRewrite rewriter= rewrite.getImportRewrite();
1530            if (enclosingImport.isStatic()) {
1531                final String JavaDoc oldImport= ASTNodes.asString(node);
1532                final StringBuffer JavaDoc buffer= new StringBuffer JavaDoc(oldImport);
1533                final String JavaDoc typeName= fType.getDeclaringType().getElementName();
1534                final int index= buffer.indexOf(typeName);
1535                if (index >= 0) {
1536                    buffer.delete(index, index + typeName.length() + 1);
1537                    final String JavaDoc newImport= buffer.toString();
1538                    if (enclosingImport.isOnDemand()) {
1539                        rewriter.removeStaticImport(oldImport + ".*"); //$NON-NLS-1$
1540
rewriter.addStaticImport(newImport, "*", false); //$NON-NLS-1$
1541
} else {
1542                        rewriter.removeStaticImport(oldImport);
1543                        final int offset= newImport.lastIndexOf('.');
1544                        if (offset >= 0 && offset < newImport.length() - 1) {
1545                            rewriter.addStaticImport(newImport.substring(0, offset), newImport.substring(offset + 1), false);
1546                        }
1547                    }
1548                }
1549            } else
1550                rewriter.removeImport(type.getQualifiedName());
1551        }
1552    }
1553
1554    private void updateTypeReference(ITypeBinding[] parameters, ASTNode node, CompilationUnitRewrite rewrite, ICompilationUnit cu) throws CoreException {
1555        ImportDeclaration enclosingImport= (ImportDeclaration) ASTNodes.getParent(node, ImportDeclaration.class);
1556        if (enclosingImport != null)
1557            updateReferenceInImport(enclosingImport, node, rewrite);
1558        else {
1559            final TextEditGroup group= rewrite.createGroupDescription(RefactoringCoreMessages.MoveInnerToTopRefactoring_update_type_reference);
1560            updateReference(parameters, node, rewrite, group);
1561            if (!fType.getPackageFragment().equals(cu.getParent())) {
1562                final String JavaDoc name= fType.getPackageFragment().getElementName() + '.' + fType.getElementName();
1563                rewrite.getImportRemover().registerAddedImport(name);
1564                rewrite.getImportRewrite().addImport(name);
1565            }
1566        }
1567    }
1568
1569    public RefactoringStatus initialize(final RefactoringArguments arguments) {
1570        if (arguments instanceof JavaRefactoringArguments) {
1571            final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments;
1572            final String JavaDoc handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT);
1573            if (handle != null) {
1574                final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
1575                if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE)
1576                    return createInputFatalStatus(element, IJavaRefactorings.CONVERT_MEMBER_TYPE);
1577                else {
1578                    fType= (IType) element;
1579                    fCodeGenerationSettings= JavaPreferencesSettings.getCodeGenerationSettings(fType.getJavaProject());
1580                    try {
1581                        initialize();
1582                    } catch (JavaModelException exception) {
1583                        JavaPlugin.log(exception);
1584                    }
1585                }
1586            } else
1587                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT));
1588            final String JavaDoc fieldName= extended.getAttribute(ATTRIBUTE_FIELD_NAME);
1589            if (fieldName != null && !"".equals(fieldName)) //$NON-NLS-1$
1590
fEnclosingInstanceFieldName= fieldName;
1591            final String JavaDoc parameterName= extended.getAttribute(ATTRIBUTE_PARAMETER_NAME);
1592            if (parameterName != null && !"".equals(parameterName)) //$NON-NLS-1$
1593
fNameForEnclosingInstanceConstructorParameter= parameterName;
1594            final String JavaDoc createField= extended.getAttribute(ATTRIBUTE_FIELD);
1595            if (createField != null) {
1596                fCreateInstanceField= Boolean.valueOf(createField).booleanValue();
1597            } else
1598                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_FIELD));
1599            final String JavaDoc markFinal= extended.getAttribute(ATTRIBUTE_FINAL);
1600            if (markFinal != null) {
1601                fMarkInstanceFieldAsFinal= Boolean.valueOf(markFinal).booleanValue();
1602            } else
1603                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_FINAL));
1604            final String JavaDoc possible= extended.getAttribute(ATTRIBUTE_POSSIBLE);
1605            if (possible != null) {
1606                fIsInstanceFieldCreationPossible= Boolean.valueOf(possible).booleanValue();
1607            } else
1608                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_POSSIBLE));
1609            final String JavaDoc mandatory= extended.getAttribute(ATTRIBUTE_MANDATORY);
1610            if (mandatory != null)
1611                fIsInstanceFieldCreationMandatory= Boolean.valueOf(mandatory).booleanValue();
1612            else
1613                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_MANDATORY));
1614        } else
1615            return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
1616        return new RefactoringStatus();
1617    }
1618}
1619
Popular Tags