KickJava   Java API By Example, From Geeks To Geeks.

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


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.Collection JavaDoc;
14 import java.util.HashSet JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.Set JavaDoc;
17
18 import org.eclipse.core.runtime.Assert;
19 import org.eclipse.core.runtime.CoreException;
20 import org.eclipse.core.runtime.IProgressMonitor;
21 import org.eclipse.core.runtime.NullProgressMonitor;
22 import org.eclipse.core.runtime.OperationCanceledException;
23 import org.eclipse.core.runtime.SubProgressMonitor;
24
25 import org.eclipse.ltk.core.refactoring.Change;
26 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
27 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
28 import org.eclipse.ltk.core.refactoring.TextChange;
29 import org.eclipse.ltk.core.refactoring.TextEditBasedChange;
30 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
31 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
32 import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
33 import org.eclipse.ltk.core.refactoring.participants.SharableParticipants;
34
35 import org.eclipse.jdt.core.ICompilationUnit;
36 import org.eclipse.jdt.core.IJavaElement;
37 import org.eclipse.jdt.core.IJavaProject;
38 import org.eclipse.jdt.core.IType;
39 import org.eclipse.jdt.core.JavaModelException;
40 import org.eclipse.jdt.core.dom.AST;
41 import org.eclipse.jdt.core.dom.ASTNode;
42 import org.eclipse.jdt.core.dom.ASTParser;
43 import org.eclipse.jdt.core.dom.ASTRequestor;
44 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
45 import org.eclipse.jdt.core.dom.CompilationUnit;
46 import org.eclipse.jdt.core.dom.IBinding;
47 import org.eclipse.jdt.core.dom.ITypeBinding;
48 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
49 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
50 import org.eclipse.jdt.core.refactoring.descriptors.UseSupertypeDescriptor;
51
52 import org.eclipse.jdt.internal.corext.dom.NodeFinder;
53 import org.eclipse.jdt.internal.corext.refactoring.Checks;
54 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor;
55 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
56 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
57 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
58 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
59 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
60 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsModel;
61 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsSolver;
62 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeRefactoringProcessor;
63 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType;
64 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ISourceConstraintVariable;
65 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeConstraintVariable;
66 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
67 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
68 import org.eclipse.jdt.internal.corext.refactoring.util.TextEditBasedChangeManager;
69 import org.eclipse.jdt.internal.corext.util.Messages;
70
71 import org.eclipse.jdt.ui.JavaElementLabels;
72
73 import org.eclipse.jdt.internal.ui.JavaPlugin;
74
75 /**
76  * Refactoring processor to replace type occurrences by a super type.
77  */

78 public final class UseSuperTypeProcessor extends SuperTypeRefactoringProcessor {
79
80     private static final String JavaDoc IDENTIFIER= "org.eclipse.jdt.ui.useSuperTypeProcessor"; //$NON-NLS-1$
81

82     /**
83      * Finds the type with the given fully qualified name (generic type
84      * parameters included) in the hierarchy.
85      *
86      * @param type
87      * The hierarchy type to find the super type in
88      * @param name
89      * The fully qualified name of the super type
90      * @return The found super type, or <code>null</code>
91      */

92     protected static ITypeBinding findTypeInHierarchy(final ITypeBinding type, final String JavaDoc name) {
93         if (type.isArray() || type.isPrimitive())
94             return null;
95         if (name.equals(type.getTypeDeclaration().getQualifiedName()))
96             return type;
97         final ITypeBinding binding= type.getSuperclass();
98         if (binding != null) {
99             final ITypeBinding result= findTypeInHierarchy(binding, name);
100             if (result != null)
101                 return result;
102         }
103         final ITypeBinding[] bindings= type.getInterfaces();
104         for (int index= 0; index < bindings.length; index++) {
105             final ITypeBinding result= findTypeInHierarchy(bindings[index], name);
106             if (result != null)
107                 return result;
108         }
109         return null;
110     }
111
112     /** The text change manager */
113     private TextEditBasedChangeManager fChangeManager= null;
114
115     /** The number of files affected by the last change generation */
116     private int fChanges= 0;
117
118     /** The subtype to replace */
119     private IType fSubType;
120
121     /** The supertype as replacement */
122     private IType fSuperType= null;
123
124     /**
125      * Creates a new super type processor.
126      *
127      * @param subType
128      * the subtype to replace its occurrences, or <code>null</code>
129      * if invoked by scripting
130      */

131     public UseSuperTypeProcessor(final IType subType) {
132         super(null);
133         fReplace= true;
134         fSubType= subType;
135     }
136
137     /**
138      * Creates a new super type processor.
139      *
140      * @param subType
141      * the subtype to replace its occurrences, or <code>null</code>
142      * if invoked by scripting
143      * @param superType
144      * the supertype as replacement, or <code>null</code> if
145      * invoked by scripting
146      */

147     public UseSuperTypeProcessor(final IType subType, final IType superType) {
148         super(null);
149         fReplace= true;
150         fSubType= subType;
151         fSuperType= superType;
152     }
153
154     /*
155      * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#checkFinalConditions(org.eclipse.core.runtime.IProgressMonitor,org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext)
156      */

157     public final RefactoringStatus checkFinalConditions(final IProgressMonitor monitor, final CheckConditionsContext context) throws CoreException, OperationCanceledException {
158         Assert.isNotNull(monitor);
159         Assert.isNotNull(context);
160         final RefactoringStatus status= new RefactoringStatus();
161         fChangeManager= new TextEditBasedChangeManager();
162         try {
163             monitor.beginTask("", 200); //$NON-NLS-1$
164
monitor.setTaskName(RefactoringCoreMessages.UseSuperTypeProcessor_checking);
165             fChangeManager= createChangeManager(new SubProgressMonitor(monitor, 200), status);
166             if (!status.hasFatalError()) {
167                 final RefactoringStatus validation= Checks.validateModifiesFiles(ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits()), getRefactoring().getValidationContext());
168                 if (!validation.isOK())
169                     return validation;
170             }
171         } finally {
172             monitor.done();
173         }
174         return status;
175     }
176
177     /*
178      * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#checkInitialConditions(org.eclipse.core.runtime.IProgressMonitor)
179      */

180     public final RefactoringStatus checkInitialConditions(final IProgressMonitor monitor) throws CoreException, OperationCanceledException {
181         Assert.isNotNull(monitor);
182         final RefactoringStatus status= new RefactoringStatus();
183         try {
184             monitor.beginTask("", 1); //$NON-NLS-1$
185
monitor.setTaskName(RefactoringCoreMessages.UseSuperTypeProcessor_checking);
186             // No checks
187
monitor.worked(1);
188         } finally {
189             monitor.done();
190         }
191         return status;
192     }
193
194     /*
195      * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#createChange(org.eclipse.core.runtime.IProgressMonitor)
196      */

197     public final Change createChange(final IProgressMonitor monitor) throws CoreException, OperationCanceledException {
198         Assert.isNotNull(monitor);
199         try {
200             fChanges= 0;
201             monitor.beginTask("", 1); //$NON-NLS-1$
202
monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating);
203             final TextEditBasedChange[] changes= fChangeManager.getAllChanges();
204             if (changes != null && changes.length != 0) {
205                 fChanges= changes.length;
206                 IJavaProject project= null;
207                 if (!fSubType.isBinary())
208                     project= fSubType.getJavaProject();
209                 int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE;
210                 try {
211                     if (fSubType.isLocal() || fSubType.isAnonymous())
212                         flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
213                 } catch (JavaModelException exception) {
214                     JavaPlugin.log(exception);
215                 }
216                 final String JavaDoc name= project != null ? project.getElementName() : null;
217                 final String JavaDoc description= Messages.format(RefactoringCoreMessages.UseSuperTypeProcessor_descriptor_description_short, fSuperType.getElementName());
218                 final String JavaDoc header= Messages.format(RefactoringCoreMessages.UseSuperTypeProcessor_descriptor_description, new String JavaDoc[] { JavaElementLabels.getElementLabel(fSuperType, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(fSubType, JavaElementLabels.ALL_FULLY_QUALIFIED) });
219                 final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(name, this, header);
220                 comment.addSetting(Messages.format(RefactoringCoreMessages.UseSuperTypeProcessor_refactored_element_pattern, JavaElementLabels.getElementLabel(fSuperType, JavaElementLabels.ALL_FULLY_QUALIFIED)));
221                 addSuperTypeSettings(comment, false);
222                 final UseSupertypeDescriptor descriptor= new UseSupertypeDescriptor();
223                 descriptor.setProject(name);
224                 descriptor.setDescription(description);
225                 descriptor.setComment(comment.asString());
226                 descriptor.setFlags(flags);
227                 descriptor.setSubtype(getSubType());
228                 descriptor.setSupertype(getSuperType());
229                 descriptor.setReplaceInstanceof(fInstanceOf);
230                 return new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.UseSupertypeWherePossibleRefactoring_name, fChangeManager.getAllChanges());
231             }
232             monitor.worked(1);
233         } finally {
234             monitor.done();
235         }
236         return null;
237     }
238
239     /**
240      * Creates the text change manager for this processor.
241      *
242      * @param monitor
243      * the progress monitor to display progress
244      * @param status
245      * the refactoring status
246      * @return the created text change manager
247      * @throws JavaModelException
248      * if the method declaration could not be found
249      * @throws CoreException
250      * if the changes could not be generated
251      */

252     protected final TextEditBasedChangeManager createChangeManager(final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException, CoreException {
253         Assert.isNotNull(status);
254         Assert.isNotNull(monitor);
255         try {
256             monitor.beginTask("", 300); //$NON-NLS-1$
257
monitor.setTaskName(RefactoringCoreMessages.UseSuperTypeProcessor_creating);
258             final TextEditBasedChangeManager manager= new TextEditBasedChangeManager();
259             final IJavaProject project= fSubType.getJavaProject();
260             final ASTParser parser= ASTParser.newParser(AST.JLS3);
261             parser.setWorkingCopyOwner(fOwner);
262             parser.setResolveBindings(true);
263             parser.setProject(project);
264             parser.setCompilerOptions(RefactoringASTParser.getCompilerOptions(project));
265             if (fSubType.isBinary() || fSubType.isReadOnly()) {
266                 final IBinding[] bindings= parser.createBindings(new IJavaElement[] { fSubType, fSuperType }, new SubProgressMonitor(monitor, 50));
267                 if (bindings != null && bindings.length == 2 && bindings[0] instanceof ITypeBinding && bindings[1] instanceof ITypeBinding) {
268                     solveSuperTypeConstraints(null, null, fSubType, (ITypeBinding) bindings[0], (ITypeBinding) bindings[1], new SubProgressMonitor(monitor, 100), status);
269                     if (!status.hasFatalError())
270                         rewriteTypeOccurrences(manager, null, null, null, null, new HashSet JavaDoc(), status, new SubProgressMonitor(monitor, 150));
271                 }
272             } else {
273                 parser.createASTs(new ICompilationUnit[] { fSubType.getCompilationUnit() }, new String JavaDoc[0], new ASTRequestor() {
274
275                     public final void acceptAST(final ICompilationUnit unit, final CompilationUnit node) {
276                         try {
277                             final CompilationUnitRewrite subRewrite= new CompilationUnitRewrite(fOwner, unit, node);
278                             final AbstractTypeDeclaration subDeclaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(fSubType, subRewrite.getRoot());
279                             if (subDeclaration != null) {
280                                 final ITypeBinding subBinding= subDeclaration.resolveBinding();
281                                 if (subBinding != null) {
282                                     final ITypeBinding superBinding= findTypeInHierarchy(subBinding, fSuperType.getFullyQualifiedName('.'));
283                                     if (superBinding != null) {
284                                         solveSuperTypeConstraints(subRewrite.getCu(), subRewrite.getRoot(), fSubType, subBinding, superBinding, new SubProgressMonitor(monitor, 100), status);
285                                         if (!status.hasFatalError()) {
286                                             rewriteTypeOccurrences(manager, this, subRewrite, subRewrite.getCu(), subRewrite.getRoot(), new HashSet JavaDoc(), status, new SubProgressMonitor(monitor, 200));
287                                             final TextChange change= subRewrite.createChange();
288                                             if (change != null)
289                                                 manager.manage(subRewrite.getCu(), change);
290                                         }
291                                     }
292                                 }
293                             }
294                         } catch (CoreException exception) {
295                             JavaPlugin.log(exception);
296                             status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.UseSuperTypeProcessor_internal_error));
297                         }
298                     }
299
300                     public final void acceptBinding(final String JavaDoc key, final IBinding binding) {
301                         // Do nothing
302
}
303                 }, new NullProgressMonitor());
304             }
305             return manager;
306         } finally {
307             monitor.done();
308         }
309     }
310
311     /*
312      * @see org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeRefactoringProcessor#createContraintSolver(org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsModel)
313      */

314     protected final SuperTypeConstraintsSolver createContraintSolver(final SuperTypeConstraintsModel model) {
315         return new SuperTypeConstraintsSolver(model);
316     }
317
318     /**
319      * Returns the number of files that are affected from the last change
320      * generation.
321      *
322      * @return The number of files which are affected
323      */

324     public final int getChanges() {
325         return fChanges;
326     }
327
328     /*
329      * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getElements()
330      */

331     public final Object JavaDoc[] getElements() {
332         return new Object JavaDoc[] { fSubType };
333     }
334
335     /*
336      * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getIdentifier()
337      */

338     public final String JavaDoc getIdentifier() {
339         return IDENTIFIER;
340     }
341
342     /*
343      * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getProcessorName()
344      */

345     public final String JavaDoc getProcessorName() {
346         return RefactoringCoreMessages.UseSuperTypeProcessor_name;
347     }
348
349     /**
350      * Returns the subtype to be replaced.
351      *
352      * @return The subtype to be replaced
353      */

354     public final IType getSubType() {
355         return fSubType;
356     }
357
358     /**
359      * Returns the supertype as replacement.
360      *
361      * @return The supertype as replacement
362      */

363     public final IType getSuperType() {
364         return fSuperType;
365     }
366
367     /**
368      * {@inheritDoc}
369      */

370     public final RefactoringStatus initialize(final RefactoringArguments arguments) {
371         if (arguments instanceof JavaRefactoringArguments) {
372             final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments;
373             String JavaDoc handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT);
374             if (handle != null) {
375                 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
376                 if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE)
377                     return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.USE_SUPER_TYPE);
378                 else
379                     fSubType= (IType) element;
380             } else
381                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT));
382             handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + 1);
383             if (handle != null) {
384                 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
385                 if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE)
386                     return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.USE_SUPER_TYPE);
387                 else
388                     fSuperType= (IType) element;
389             } else
390                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + 1));
391             final String JavaDoc instance= extended.getAttribute(ATTRIBUTE_INSTANCEOF);
392             if (instance != null) {
393                 fInstanceOf= Boolean.valueOf(instance).booleanValue();
394             } else
395                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_INSTANCEOF));
396         } else
397             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
398         return new RefactoringStatus();
399     }
400
401     /*
402      * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#isApplicable()
403      */

404     public final boolean isApplicable() throws CoreException {
405         return Checks.isAvailable(fSubType) && Checks.isAvailable(fSuperType) && !fSubType.isAnonymous() && !fSubType.isAnnotation() && !fSuperType.isAnonymous() && !fSuperType.isAnnotation() && !fSuperType.isEnum();
406     }
407
408     /*
409      * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#loadParticipants(org.eclipse.ltk.core.refactoring.RefactoringStatus,org.eclipse.ltk.core.refactoring.participants.SharableParticipants)
410      */

411     public final RefactoringParticipant[] loadParticipants(final RefactoringStatus status, final SharableParticipants sharedParticipants) throws CoreException {
412         return new RefactoringParticipant[0];
413     }
414
415     /**
416      * {@inheritDoc}
417      */

418     protected final void rewriteTypeOccurrences(final TextEditBasedChangeManager manager, final ASTRequestor requestor, final CompilationUnitRewrite rewrite, final ICompilationUnit unit, final CompilationUnit node, final Set JavaDoc replacements, final IProgressMonitor monitor) throws CoreException {
419         try {
420             monitor.beginTask("", 100); //$NON-NLS-1$
421
monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating);
422             final Collection JavaDoc collection= (Collection JavaDoc) fTypeOccurrences.get(unit);
423             if (collection != null && !collection.isEmpty()) {
424                 final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 100);
425                 try {
426                     subMonitor.beginTask("", collection.size() * 10); //$NON-NLS-1$
427
subMonitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating);
428                     TType estimate= null;
429                     ISourceConstraintVariable variable= null;
430                     CompilationUnitRewrite currentRewrite= null;
431                     final ICompilationUnit sourceUnit= rewrite.getCu();
432                     if (sourceUnit.equals(unit))
433                         currentRewrite= rewrite;
434                     else
435                         currentRewrite= new CompilationUnitRewrite(fOwner, unit, node);
436                     for (final Iterator JavaDoc iterator= collection.iterator(); iterator.hasNext();) {
437                         variable= (ISourceConstraintVariable) iterator.next();
438                         estimate= (TType) variable.getData(SuperTypeConstraintsSolver.DATA_TYPE_ESTIMATE);
439                         if (estimate != null && variable instanceof ITypeConstraintVariable) {
440                             final ASTNode result= NodeFinder.perform(node, ((ITypeConstraintVariable) variable).getRange().getSourceRange());
441                             if (result != null)
442                                 rewriteTypeOccurrence(estimate, currentRewrite, result, currentRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.SuperTypeRefactoringProcessor_update_type_occurrence, SET_SUPER_TYPE));
443                         }
444                         subMonitor.worked(10);
445                     }
446                     if (!sourceUnit.equals(unit)) {
447                         final TextChange change= currentRewrite.createChange();
448                         if (change != null)
449                             manager.manage(unit, change);
450                     }
451                 } finally {
452                     subMonitor.done();
453                 }
454             }
455         } finally {
456             monitor.done();
457         }
458     }
459
460     /**
461      * Sets the supertype as replacement.
462      *
463      * @param type
464      * The supertype to set
465      */

466     public final void setSuperType(final IType type) {
467         Assert.isNotNull(type);
468
469         fSuperType= type;
470     }
471 }
472
Popular Tags