KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 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.HashMap JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Map JavaDoc;
19
20 import org.eclipse.text.edits.MalformedTreeException;
21 import org.eclipse.text.edits.TextEdit;
22
23 import org.eclipse.core.runtime.IProgressMonitor;
24 import org.eclipse.core.runtime.SubProgressMonitor;
25
26 import org.eclipse.jface.text.BadLocationException;
27 import org.eclipse.jface.text.Document;
28 import org.eclipse.jface.text.IDocument;
29 import org.eclipse.jface.text.TextUtilities;
30
31 import org.eclipse.ltk.core.refactoring.Refactoring;
32 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
33 import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
34
35 import org.eclipse.jdt.core.Flags;
36 import org.eclipse.jdt.core.ICompilationUnit;
37 import org.eclipse.jdt.core.IField;
38 import org.eclipse.jdt.core.IInitializer;
39 import org.eclipse.jdt.core.IMember;
40 import org.eclipse.jdt.core.IMethod;
41 import org.eclipse.jdt.core.ISourceRange;
42 import org.eclipse.jdt.core.IType;
43 import org.eclipse.jdt.core.ITypeHierarchy;
44 import org.eclipse.jdt.core.JavaModelException;
45 import org.eclipse.jdt.core.dom.AST;
46 import org.eclipse.jdt.core.dom.ASTNode;
47 import org.eclipse.jdt.core.dom.ASTVisitor;
48 import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
49 import org.eclipse.jdt.core.dom.BodyDeclaration;
50 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
51 import org.eclipse.jdt.core.dom.CompilationUnit;
52 import org.eclipse.jdt.core.dom.EnumDeclaration;
53 import org.eclipse.jdt.core.dom.Expression;
54 import org.eclipse.jdt.core.dom.FieldDeclaration;
55 import org.eclipse.jdt.core.dom.ITypeBinding;
56 import org.eclipse.jdt.core.dom.Javadoc;
57 import org.eclipse.jdt.core.dom.MethodDeclaration;
58 import org.eclipse.jdt.core.dom.Modifier;
59 import org.eclipse.jdt.core.dom.Name;
60 import org.eclipse.jdt.core.dom.SimpleName;
61 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
62 import org.eclipse.jdt.core.dom.Type;
63 import org.eclipse.jdt.core.dom.TypeDeclaration;
64 import org.eclipse.jdt.core.dom.TypeParameter;
65 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
66 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
67 import org.eclipse.jdt.core.dom.rewrite.ITrackedNodePosition;
68 import org.eclipse.jdt.core.search.IJavaSearchConstants;
69 import org.eclipse.jdt.core.search.SearchMatch;
70 import org.eclipse.jdt.core.search.SearchPattern;
71
72 import org.eclipse.jdt.internal.corext.Assert;
73 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
74 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
75 import org.eclipse.jdt.internal.corext.dom.ModifierRewrite;
76 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
77 import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory;
78 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine2;
79 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
80 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
81 import org.eclipse.jdt.internal.corext.refactoring.reorg.SourceReferenceUtil;
82 import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
83 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
84 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
85 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
86 import org.eclipse.jdt.internal.corext.util.JdtFlags;
87 import org.eclipse.jdt.internal.corext.util.Messages;
88 import org.eclipse.jdt.internal.corext.util.SearchUtils;
89 import org.eclipse.jdt.internal.corext.util.Strings;
90 import org.eclipse.jdt.internal.corext.util.WorkingCopyUtil;
91
92 import org.eclipse.jdt.internal.ui.JavaPlugin;
93
94 /**
95  * Partial implementation of a refactoring executed on type hierarchies.
96  */

97 public abstract class HierarchyRefactoring extends Refactoring {
98
99     /**
100      * AST node visitor which performs the actual mapping.
101      */

102     public static class TypeVariableMapper extends ASTVisitor {
103
104         /** The type variable mapping to use */
105         protected final TypeVariableMaplet[] fMapping;
106
107         /** The AST rewrite to use */
108         protected final ASTRewrite fRewrite;
109
110         /**
111          * Creates a new type variable mapper.
112          *
113          * @param rewrite The AST rewrite to use
114          * @param mapping The type variable mapping to use
115          */

116         public TypeVariableMapper(final ASTRewrite rewrite, final TypeVariableMaplet[] mapping) {
117             Assert.isNotNull(rewrite);
118             Assert.isNotNull(mapping);
119             fRewrite= rewrite;
120             fMapping= mapping;
121         }
122
123         public final boolean visit(final SimpleName node) {
124             final ITypeBinding binding= node.resolveTypeBinding();
125             if (binding != null && binding.isTypeVariable()) {
126                 String JavaDoc name= null;
127                 for (int index= 0; index < fMapping.length; index++) {
128                     name= binding.getName();
129                     if (fMapping[index].getSourceName().equals(name) && node.getIdentifier().equals(name))
130                         fRewrite.set(node, SimpleName.IDENTIFIER_PROPERTY, fMapping[index].getTargetName(), null);
131                 }
132             }
133             return true;
134         }
135     }
136
137     protected static boolean areAllFragmentsDeleted(final FieldDeclaration declaration, final List JavaDoc declarationNodes) {
138         for (final Iterator JavaDoc iterator= declaration.fragments().iterator(); iterator.hasNext();) {
139             if (!declarationNodes.contains(iterator.next()))
140                 return false;
141         }
142         return true;
143     }
144
145     protected static RefactoringStatus checkCallsToClassConstructors(final IType type, final IProgressMonitor monitor) throws JavaModelException {
146         final RefactoringStatus result= new RefactoringStatus();
147         final SearchResultGroup[] groups= ConstructorReferenceFinder.getConstructorReferences(type, monitor, result);
148         final String JavaDoc message= Messages.format(RefactoringCoreMessages.HierarchyRefactoring_gets_instantiated, new Object JavaDoc[] { createTypeLabel(type)});
149
150         ICompilationUnit unit= null;
151         for (int index= 0; index < groups.length; index++) {
152             unit= groups[index].getCompilationUnit();
153             if (unit != null) {
154                 final CompilationUnit cuNode= new RefactoringASTParser(AST.JLS3).parse(unit, false);
155                 final ASTNode[] references= ASTNodeSearchUtil.getAstNodes(groups[index].getSearchResults(), cuNode);
156                 ASTNode node= null;
157                 for (int offset= 0; offset < references.length; offset++) {
158                     node= references[offset];
159                     if ((node instanceof ClassInstanceCreation) || ConstructorReferenceFinder.isImplicitConstructorReferenceNodeInClassCreations(node)) {
160                         RefactoringStatusContext context= JavaStatusContext.create(unit, node);
161                         result.addError(message, context);
162                     }
163                 }
164             }
165         }
166         monitor.done();
167         return result;
168     }
169
170     protected static void copyJavadocNode(final ASTRewrite rewrite, final IMember member, final BodyDeclaration oldDeclaration, final BodyDeclaration newDeclaration) throws JavaModelException {
171         final Javadoc predecessor= oldDeclaration.getJavadoc();
172         if (predecessor != null) {
173             final IDocument buffer= new Document(member.getCompilationUnit().getBuffer().getContents());
174             try {
175                 final String JavaDoc[] lines= Strings.convertIntoLines(buffer.get(predecessor.getStartPosition(), predecessor.getLength()));
176                 Strings.trimIndentation(lines, member.getJavaProject(), false);
177                 final Javadoc successor= (Javadoc) rewrite.createStringPlaceholder(Strings.concatenate(lines, TextUtilities.getDefaultLineDelimiter(buffer)), ASTNode.JAVADOC);
178                 newDeclaration.setJavadoc(successor);
179             } catch (BadLocationException exception) {
180                 JavaPlugin.log(exception);
181             }
182         }
183     }
184
185     protected static void copyThrownExceptions(MethodDeclaration oldMethod, MethodDeclaration newMethod) {
186         final AST ast= newMethod.getAST();
187         for (int index= 0, n= oldMethod.thrownExceptions().size(); index < n; index++)
188             newMethod.thrownExceptions().add(index, ASTNode.copySubtree(ast, (Name) oldMethod.thrownExceptions().get(index)));
189     }
190
191     protected static void copyTypeParameters(MethodDeclaration oldMethod, MethodDeclaration newMethod) {
192         final AST ast= newMethod.getAST();
193         for (int index= 0, n= oldMethod.typeParameters().size(); index < n; index++)
194             newMethod.typeParameters().add(index, ASTNode.copySubtree(ast, (TypeParameter) oldMethod.typeParameters().get(index)));
195     }
196
197     protected static String JavaDoc createFieldLabel(final IField field) {
198         return field.getElementName();
199     }
200
201     protected static String JavaDoc createLabel(final IMember member) {
202         if (member instanceof IType)
203             return createTypeLabel((IType) member);
204         else if (member instanceof IMethod)
205             return createMethodLabel((IMethod) member);
206         else if (member instanceof IField)
207             return createFieldLabel((IField) member);
208         else if (member instanceof IInitializer)
209             return RefactoringCoreMessages.HierarchyRefactoring_initializer;
210         Assert.isTrue(false);
211         return null;
212     }
213
214     protected static String JavaDoc createMethodLabel(final IMethod method) {
215         return JavaElementUtil.createMethodSignature(method);
216     }
217
218     protected static FieldDeclaration createNewFieldDeclarationNode(final ASTRewrite rewrite, final CompilationUnit unit, final IField field, final VariableDeclarationFragment oldFieldFragment, final TypeVariableMaplet[] mapping, final IProgressMonitor monitor, final RefactoringStatus status, final int modifiers) throws JavaModelException {
219         final VariableDeclarationFragment newFragment= rewrite.getAST().newVariableDeclarationFragment();
220         newFragment.setExtraDimensions(oldFieldFragment.getExtraDimensions());
221         if (oldFieldFragment.getInitializer() != null) {
222             Expression newInitializer= null;
223             if (mapping.length > 0)
224                 newInitializer= createPlaceholderForExpression(oldFieldFragment.getInitializer(), field.getCompilationUnit(), mapping, rewrite);
225             else
226                 newInitializer= createPlaceholderForExpression(oldFieldFragment.getInitializer(), field.getCompilationUnit(), rewrite);
227             newFragment.setInitializer(newInitializer);
228         }
229         newFragment.setName(((SimpleName) ASTNode.copySubtree(rewrite.getAST(), oldFieldFragment.getName())));
230         final FieldDeclaration newField= rewrite.getAST().newFieldDeclaration(newFragment);
231         final FieldDeclaration oldField= ASTNodeSearchUtil.getFieldDeclarationNode(field, unit);
232         copyJavadocNode(rewrite, field, oldField, newField);
233         newField.modifiers().addAll(ASTNodeFactory.newModifiers(rewrite.getAST(), modifiers));
234         Type oldType= oldField.getType();
235         Type newType= null;
236         if (mapping.length > 0) {
237             newType= createPlaceholderForType(oldType, field.getCompilationUnit(), mapping, rewrite);
238         } else
239             newType= createPlaceholderForType(oldType, field.getCompilationUnit(), rewrite);
240         newField.setType(newType);
241         return newField;
242     }
243
244     protected static Expression createPlaceholderForExpression(final Expression expression, final ICompilationUnit declaringCu, final ASTRewrite rewrite) throws JavaModelException {
245         return (Expression) rewrite.createStringPlaceholder(declaringCu.getBuffer().getText(expression.getStartPosition(), expression.getLength()), ASTNode.METHOD_INVOCATION);
246     }
247
248     protected static Expression createPlaceholderForExpression(final Expression expression, final ICompilationUnit declaringCu, final TypeVariableMaplet[] mapping, final ASTRewrite rewrite) throws JavaModelException {
249         Expression result= null;
250         try {
251             final IDocument document= new Document(declaringCu.getBuffer().getContents());
252             final ASTRewrite rewriter= ASTRewrite.create(expression.getAST());
253             final ITrackedNodePosition position= rewriter.track(expression);
254             expression.accept(new TypeVariableMapper(rewriter, mapping));
255             rewriter.rewriteAST(document, declaringCu.getJavaProject().getOptions(true)).apply(document, TextEdit.NONE);
256             result= (Expression) rewrite.createStringPlaceholder(document.get(position.getStartPosition(), position.getLength()), ASTNode.METHOD_INVOCATION);
257         } catch (MalformedTreeException exception) {
258             JavaPlugin.log(exception);
259         } catch (BadLocationException exception) {
260             JavaPlugin.log(exception);
261         }
262         return result;
263     }
264
265     protected static BodyDeclaration createPlaceholderForProtectedTypeDeclaration(final BodyDeclaration bodyDeclaration, final CompilationUnit declaringCuNode, final ICompilationUnit declaringCu, final ASTRewrite rewrite, final boolean removeIndentation) throws JavaModelException {
266         String JavaDoc text= null;
267         try {
268             final ASTRewrite rewriter= ASTRewrite.create(bodyDeclaration.getAST());
269             ModifierRewrite.create(rewriter, bodyDeclaration).setVisibility(Modifier.PROTECTED, null);
270             final ITrackedNodePosition position= rewriter.track(bodyDeclaration);
271             final IDocument document= new Document(declaringCu.getBuffer().getText(declaringCuNode.getStartPosition(), declaringCuNode.getLength()));
272             rewriter.rewriteAST(document, declaringCu.getJavaProject().getOptions(true)).apply(document, TextEdit.UPDATE_REGIONS);
273             text= document.get(position.getStartPosition(), position.getLength());
274         } catch (BadLocationException exception) {
275             text= getNewText(bodyDeclaration, declaringCu, removeIndentation);
276         }
277         return (BodyDeclaration) rewrite.createStringPlaceholder(text, ASTNode.TYPE_DECLARATION);
278     }
279
280     protected static BodyDeclaration createPlaceholderForProtectedTypeDeclaration(final BodyDeclaration bodyDeclaration, final CompilationUnit declaringCuNode, final ICompilationUnit declaringCu, final TypeVariableMaplet[] mapping, final ASTRewrite rewrite, final boolean removeIndentation) throws JavaModelException {
281         BodyDeclaration result= null;
282         try {
283             final IDocument document= new Document(declaringCu.getBuffer().getContents());
284             final ASTRewrite rewriter= ASTRewrite.create(bodyDeclaration.getAST());
285             final ITrackedNodePosition position= rewriter.track(bodyDeclaration);
286             bodyDeclaration.accept(new TypeVariableMapper(rewriter, mapping) {
287
288                 public final boolean visit(final AnnotationTypeDeclaration node) {
289                     ModifierRewrite.create(fRewrite, bodyDeclaration).setVisibility(Modifier.PROTECTED, null);
290                     return true;
291                 }
292
293                 public final boolean visit(final EnumDeclaration node) {
294                     ModifierRewrite.create(fRewrite, bodyDeclaration).setVisibility(Modifier.PROTECTED, null);
295                     return true;
296                 }
297
298                 public final boolean visit(final TypeDeclaration node) {
299                     ModifierRewrite.create(fRewrite, bodyDeclaration).setVisibility(Modifier.PROTECTED, null);
300                     return true;
301                 }
302             });
303             rewriter.rewriteAST(document, declaringCu.getJavaProject().getOptions(true)).apply(document, TextEdit.NONE);
304             result= (BodyDeclaration) rewrite.createStringPlaceholder(document.get(position.getStartPosition(), position.getLength()), ASTNode.TYPE_DECLARATION);
305         } catch (MalformedTreeException exception) {
306             JavaPlugin.log(exception);
307         } catch (BadLocationException exception) {
308             JavaPlugin.log(exception);
309         }
310         return result;
311     }
312
313     protected static SingleVariableDeclaration createPlaceholderForSingleVariableDeclaration(final SingleVariableDeclaration declaration, final ICompilationUnit declaringCu, final ASTRewrite rewrite) throws JavaModelException {
314         return (SingleVariableDeclaration) rewrite.createStringPlaceholder(declaringCu.getBuffer().getText(declaration.getStartPosition(), declaration.getLength()), ASTNode.SINGLE_VARIABLE_DECLARATION);
315     }
316
317     protected static SingleVariableDeclaration createPlaceholderForSingleVariableDeclaration(final SingleVariableDeclaration declaration, final ICompilationUnit declaringCu, final TypeVariableMaplet[] mapping, final ASTRewrite rewrite) throws JavaModelException {
318         SingleVariableDeclaration result= null;
319         try {
320             final IDocument document= new Document(declaringCu.getBuffer().getContents());
321             final ASTRewrite rewriter= ASTRewrite.create(declaration.getAST());
322             final ITrackedNodePosition position= rewriter.track(declaration);
323             declaration.accept(new TypeVariableMapper(rewriter, mapping));
324             rewriter.rewriteAST(document, declaringCu.getJavaProject().getOptions(true)).apply(document, TextEdit.NONE);
325             result= (SingleVariableDeclaration) rewrite.createStringPlaceholder(document.get(position.getStartPosition(), position.getLength()), ASTNode.SINGLE_VARIABLE_DECLARATION);
326         } catch (MalformedTreeException exception) {
327             JavaPlugin.log(exception);
328         } catch (BadLocationException exception) {
329             JavaPlugin.log(exception);
330         }
331         return result;
332     }
333
334     protected static Type createPlaceholderForType(final Type type, final ICompilationUnit declaringCu, final ASTRewrite rewrite) throws JavaModelException {
335         return (Type) rewrite.createStringPlaceholder(declaringCu.getBuffer().getText(type.getStartPosition(), type.getLength()), ASTNode.SIMPLE_TYPE);
336     }
337
338     protected static Type createPlaceholderForType(final Type type, final ICompilationUnit declaringCu, final TypeVariableMaplet[] mapping, final ASTRewrite rewrite) throws JavaModelException {
339         Type result= null;
340         try {
341             final IDocument document= new Document(declaringCu.getBuffer().getContents());
342             final ASTRewrite rewriter= ASTRewrite.create(type.getAST());
343             final ITrackedNodePosition position= rewriter.track(type);
344             type.accept(new TypeVariableMapper(rewriter, mapping));
345             rewriter.rewriteAST(document, declaringCu.getJavaProject().getOptions(true)).apply(document, TextEdit.NONE);
346             result= (Type) rewrite.createStringPlaceholder(document.get(position.getStartPosition(), position.getLength()), ASTNode.SIMPLE_TYPE);
347         } catch (MalformedTreeException exception) {
348             JavaPlugin.log(exception);
349         } catch (BadLocationException exception) {
350             JavaPlugin.log(exception);
351         }
352         return result;
353     }
354
355     protected static BodyDeclaration createPlaceholderForTypeDeclaration(final BodyDeclaration bodyDeclaration, final ICompilationUnit declaringCu, final ASTRewrite rewrite, final boolean removeIndentation) throws JavaModelException {
356         return (BodyDeclaration) rewrite.createStringPlaceholder(getNewText(bodyDeclaration, declaringCu, removeIndentation), ASTNode.TYPE_DECLARATION);
357     }
358
359     protected static BodyDeclaration createPlaceholderForTypeDeclaration(final BodyDeclaration bodyDeclaration, final ICompilationUnit declaringCu, final TypeVariableMaplet[] mapping, final ASTRewrite rewrite, final boolean removeIndentation) throws JavaModelException {
360         BodyDeclaration result= null;
361         try {
362             final IDocument document= new Document(declaringCu.getBuffer().getContents());
363             final ASTRewrite rewriter= ASTRewrite.create(bodyDeclaration.getAST());
364             final ITrackedNodePosition position= rewriter.track(bodyDeclaration);
365             bodyDeclaration.accept(new TypeVariableMapper(rewriter, mapping));
366             rewriter.rewriteAST(document, declaringCu.getJavaProject().getOptions(true)).apply(document, TextEdit.NONE);
367             result= (BodyDeclaration) rewrite.createStringPlaceholder(document.get(position.getStartPosition(), position.getLength()), ASTNode.TYPE_DECLARATION);
368         } catch (MalformedTreeException exception) {
369             JavaPlugin.log(exception);
370         } catch (BadLocationException exception) {
371             JavaPlugin.log(exception);
372         }
373         return result;
374     }
375
376     protected static String JavaDoc createTypeLabel(final IType type) {
377         return JavaModelUtil.getFullyQualifiedName(type);
378     }
379
380     protected static void deleteDeclarationNodes(final CompilationUnitRewrite sourceRewriter, final boolean sameCu, final CompilationUnitRewrite unitRewriter, final List JavaDoc members) throws JavaModelException {
381         final List JavaDoc declarationNodes= getDeclarationNodes(unitRewriter.getRoot(), members);
382         for (final Iterator JavaDoc iterator= declarationNodes.iterator(); iterator.hasNext();) {
383             final ASTNode node= (ASTNode) iterator.next();
384             final ASTRewrite rewriter= unitRewriter.getASTRewrite();
385             final ImportRemover remover= unitRewriter.getImportRemover();
386             if (node instanceof VariableDeclarationFragment) {
387                 if (node.getParent() instanceof FieldDeclaration) {
388                     final FieldDeclaration declaration= (FieldDeclaration) node.getParent();
389                     if (areAllFragmentsDeleted(declaration, declarationNodes)) {
390                         rewriter.remove(declaration, unitRewriter.createGroupDescription(RefactoringCoreMessages.HierarchyRefactoring_remove_member));
391                         if (!sameCu)
392                             remover.registerRemovedNode(declaration);
393                     } else {
394                         rewriter.remove(node, unitRewriter.createGroupDescription(RefactoringCoreMessages.HierarchyRefactoring_remove_member));
395                         if (!sameCu)
396                             remover.registerRemovedNode(node);
397                     }
398                 }
399             } else {
400                 rewriter.remove(node, unitRewriter.createGroupDescription(RefactoringCoreMessages.HierarchyRefactoring_remove_member));
401                 if (!sameCu)
402                     remover.registerRemovedNode(node);
403             }
404         }
405     }
406
407     protected static List JavaDoc getDeclarationNodes(final CompilationUnit cuNode, final List JavaDoc members) throws JavaModelException {
408         final List JavaDoc result= new ArrayList JavaDoc(members.size());
409         for (final Iterator JavaDoc iterator= members.iterator(); iterator.hasNext();) {
410             final IMember member= (IMember) iterator.next();
411             ASTNode node= null;
412             if (member instanceof IField) {
413                 if (Flags.isEnum(member.getFlags()))
414                     node= ASTNodeSearchUtil.getEnumConstantDeclaration((IField) member, cuNode);
415                 else
416                     node= ASTNodeSearchUtil.getFieldDeclarationFragmentNode((IField) member, cuNode);
417             } else if (member instanceof IType)
418                 node= ASTNodeSearchUtil.getAbstractTypeDeclarationNode((IType) member, cuNode);
419             else if (member instanceof IMethod)
420                 node= ASTNodeSearchUtil.getMethodDeclarationNode((IMethod) member, cuNode);
421             if (node != null)
422                 result.add(node);
423         }
424         return result;
425     }
426
427     protected static String JavaDoc getNewText(final ASTNode node, final ICompilationUnit declaringCu, final boolean removeIndentation) throws JavaModelException {
428         final String JavaDoc result= declaringCu.getBuffer().getText(node.getStartPosition(), node.getLength());
429         if (removeIndentation)
430             return getUnindentedText(result, declaringCu);
431
432         return result;
433     }
434
435     protected static String JavaDoc getUnindentedText(final String JavaDoc text, final ICompilationUnit declaringCu) throws JavaModelException {
436         final String JavaDoc[] lines= Strings.convertIntoLines(text);
437         Strings.trimIndentation(lines, declaringCu.getJavaProject(), false);
438         return Strings.concatenate(lines, StubUtility.getLineDelimiterUsed(declaringCu));
439     }
440
441     protected final Map JavaDoc fCachedMembersReferences= new HashMap JavaDoc(2);
442
443     protected IType[] fCachedReferencedTypes;
444
445     protected TextChangeManager fChangeManager;
446
447     protected IType fDeclaringType;
448
449     protected IMember[] fMembersToMove;
450
451     protected HierarchyRefactoring(final IMember[] members) {
452         Assert.isNotNull(members);
453         fMembersToMove= (IMember[]) SourceReferenceUtil.sortByOffset(members);
454     }
455
456     protected boolean canBeAccessedFrom(final IMember member, final IType target, final ITypeHierarchy hierarchy) throws JavaModelException {
457         Assert.isTrue(!(member instanceof IInitializer));
458
459         return member.exists();
460     }
461
462     protected RefactoringStatus checkDeclaringType(final IProgressMonitor monitor) throws JavaModelException {
463         final IType type= getDeclaringType();
464         if (type.isEnum())
465             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.HierarchyRefactoring_enum_members);
466         if (type.isAnnotation())
467             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.HierarchyRefactoring_annotation_members);
468         if (type.isInterface())
469             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.HierarchyRefactoring_interface_members);
470         if (type.isBinary())
471             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.HierarchyRefactoring_members_of_binary);
472         if (type.isReadOnly())
473             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.HierarchyRefactoring_members_of_read_only);
474         return new RefactoringStatus();
475     }
476
477     protected RefactoringStatus checkIfMembersExist() {
478         RefactoringStatus result= new RefactoringStatus();
479         IMember member= null;
480         for (int index= 0; index < fMembersToMove.length; index++) {
481             member= fMembersToMove[index];
482             if (member == null || !member.exists())
483                 result.addFatalError(RefactoringCoreMessages.HierarchyRefactoring_does_not_exist);
484         }
485         return result;
486     }
487
488     protected void clearCaches() {
489         fCachedReferencedTypes= null;
490     }
491
492     protected void copyParameters(final ASTRewrite rewrite, final ICompilationUnit unit, final MethodDeclaration oldMethod, final MethodDeclaration newMethod, final TypeVariableMaplet[] mapping) throws JavaModelException {
493         SingleVariableDeclaration newDeclaration= null;
494         for (int index= 0, size= oldMethod.parameters().size(); index < size; index++) {
495             SingleVariableDeclaration oldDeclaration= (SingleVariableDeclaration) oldMethod.parameters().get(index);
496             if (mapping.length > 0)
497                 newDeclaration= createPlaceholderForSingleVariableDeclaration(oldDeclaration, unit, mapping, rewrite);
498             else
499                 newDeclaration= createPlaceholderForSingleVariableDeclaration(oldDeclaration, unit, rewrite);
500             newMethod.parameters().add(index, newDeclaration);
501         }
502     }
503
504     protected void copyReturnType(final ASTRewrite rewrite, final ICompilationUnit unit, final MethodDeclaration oldMethod, final MethodDeclaration newMethod, final TypeVariableMaplet[] mapping) throws JavaModelException {
505         Type newReturnType= null;
506         if (mapping.length > 0)
507             newReturnType= createPlaceholderForType(oldMethod.getReturnType2(), unit, mapping, rewrite);
508         else
509             newReturnType= createPlaceholderForType(oldMethod.getReturnType2(), unit, rewrite);
510         newMethod.setReturnType2(newReturnType);
511     }
512
513     public IType getDeclaringType() {
514         if (fDeclaringType != null)
515             return fDeclaringType;
516         fDeclaringType= (IType) WorkingCopyUtil.getOriginal(fMembersToMove[0].getDeclaringType());
517         return fDeclaringType;
518     }
519
520     public IMember[] getMembersToMove() {
521         return fMembersToMove;
522     }
523
524     protected IType[] getTypesReferencedInMovedMembers(final IProgressMonitor monitor) throws JavaModelException {
525         if (fCachedReferencedTypes == null) {
526             final IType[] types= ReferenceFinderUtil.getTypesReferencedIn(fMembersToMove, monitor);
527             final List JavaDoc result= new ArrayList JavaDoc(types.length);
528             final List JavaDoc members= Arrays.asList(fMembersToMove);
529             for (int index= 0; index < types.length; index++) {
530                 if (!members.contains(types[index]) && types[index] != getDeclaringType())
531                     result.add(types[index]);
532             }
533             fCachedReferencedTypes= new IType[result.size()];
534             result.toArray(fCachedReferencedTypes);
535         }
536         return fCachedReferencedTypes;
537     }
538
539     protected boolean hasNonMovedReferences(final IMember member, final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException {
540         if (!fCachedMembersReferences.containsKey(member)) {
541             final RefactoringSearchEngine2 engine= new RefactoringSearchEngine2(SearchPattern.createPattern(member, IJavaSearchConstants.REFERENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE));
542             engine.setFiltering(true, true);
543             engine.setStatus(status);
544             engine.setScope(RefactoringScopeFactory.create(member));
545             engine.searchPattern(new SubProgressMonitor(monitor, 1));
546             fCachedMembersReferences.put(member, engine.getResults());
547         }
548         final SearchResultGroup[] groups= (SearchResultGroup[]) fCachedMembersReferences.get(member);
549         if (groups.length == 0)
550             return false;
551         else if (groups.length > 1)
552             return true;
553         final ICompilationUnit unit= groups[0].getCompilationUnit();
554         if (!getDeclaringType().getCompilationUnit().equals(unit))
555             return true;
556         final SearchMatch[] matches= groups[0].getSearchResults();
557         for (int index= 0; index < matches.length; index++) {
558             if (!isMovedReference(matches[index]))
559                 return true;
560         }
561         return false;
562     }
563
564     protected boolean isMovedReference(final SearchMatch match) throws JavaModelException {
565         ISourceRange range= null;
566         for (int index= 0; index < fMembersToMove.length; index++) {
567             range= fMembersToMove[index].getSourceRange();
568             if (range.getOffset() <= match.getOffset() && range.getOffset() + range.getLength() >= match.getOffset())
569                 return true;
570         }
571         return false;
572     }
573
574     protected boolean needsVisibilityAdjustment(final IMember member, final boolean references, final IProgressMonitor monitor, RefactoringStatus status) throws JavaModelException {
575         if (JdtFlags.isPublic(member) || JdtFlags.isProtected(member))
576             return false;
577         if (!references)
578             return true;
579         return hasNonMovedReferences(member, monitor, status);
580     }
581 }
582
Popular Tags