KickJava   Java API By Example, From Geeks To Geeks.

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


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.Comparator JavaDoc;
17 import java.util.HashMap JavaDoc;
18 import java.util.HashSet JavaDoc;
19 import java.util.Iterator 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.MalformedTreeException;
25 import org.eclipse.text.edits.TextEdit;
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.OperationCanceledException;
32 import org.eclipse.core.runtime.SubProgressMonitor;
33
34 import org.eclipse.core.filebuffers.ITextFileBuffer;
35
36 import org.eclipse.core.resources.IFile;
37
38 import org.eclipse.jface.text.BadLocationException;
39 import org.eclipse.jface.text.Document;
40 import org.eclipse.jface.text.IDocument;
41
42 import org.eclipse.ltk.core.refactoring.Change;
43 import org.eclipse.ltk.core.refactoring.GroupCategory;
44 import org.eclipse.ltk.core.refactoring.GroupCategorySet;
45 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
46 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
47 import org.eclipse.ltk.core.refactoring.TextChange;
48 import org.eclipse.ltk.core.refactoring.TextEditBasedChange;
49 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
50 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
51 import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
52 import org.eclipse.ltk.core.refactoring.participants.SharableParticipants;
53
54 import org.eclipse.jdt.core.ICompilationUnit;
55 import org.eclipse.jdt.core.IField;
56 import org.eclipse.jdt.core.IJavaElement;
57 import org.eclipse.jdt.core.IJavaProject;
58 import org.eclipse.jdt.core.IMember;
59 import org.eclipse.jdt.core.IMethod;
60 import org.eclipse.jdt.core.IPackageFragment;
61 import org.eclipse.jdt.core.ISourceReference;
62 import org.eclipse.jdt.core.IType;
63 import org.eclipse.jdt.core.ITypeParameter;
64 import org.eclipse.jdt.core.JavaCore;
65 import org.eclipse.jdt.core.JavaModelException;
66 import org.eclipse.jdt.core.dom.AST;
67 import org.eclipse.jdt.core.dom.ASTNode;
68 import org.eclipse.jdt.core.dom.ASTParser;
69 import org.eclipse.jdt.core.dom.ASTRequestor;
70 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
71 import org.eclipse.jdt.core.dom.Annotation;
72 import org.eclipse.jdt.core.dom.CompilationUnit;
73 import org.eclipse.jdt.core.dom.EnumDeclaration;
74 import org.eclipse.jdt.core.dom.FieldDeclaration;
75 import org.eclipse.jdt.core.dom.IBinding;
76 import org.eclipse.jdt.core.dom.IExtendedModifier;
77 import org.eclipse.jdt.core.dom.IMethodBinding;
78 import org.eclipse.jdt.core.dom.ITypeBinding;
79 import org.eclipse.jdt.core.dom.IVariableBinding;
80 import org.eclipse.jdt.core.dom.MethodDeclaration;
81 import org.eclipse.jdt.core.dom.Modifier;
82 import org.eclipse.jdt.core.dom.ParameterizedType;
83 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
84 import org.eclipse.jdt.core.dom.Type;
85 import org.eclipse.jdt.core.dom.TypeDeclaration;
86 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
87 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
88 import org.eclipse.jdt.core.dom.rewrite.ITrackedNodePosition;
89 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
90 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
91 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
92
93 import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
94 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
95 import org.eclipse.jdt.internal.corext.dom.Bindings;
96 import org.eclipse.jdt.internal.corext.dom.ModifierRewrite;
97 import org.eclipse.jdt.internal.corext.dom.NodeFinder;
98 import org.eclipse.jdt.internal.corext.refactoring.Checks;
99 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
100 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor;
101 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
102 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
103 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
104 import org.eclipse.jdt.internal.corext.refactoring.changes.CreateCompilationUnitChange;
105 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
106 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
107 import org.eclipse.jdt.internal.corext.refactoring.reorg.ASTNodeDeleteUtil;
108 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsModel;
109 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsSolver;
110 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeRefactoringProcessor;
111 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompilationUnitRange;
112 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType;
113 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ISourceConstraintVariable;
114 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeConstraintVariable;
115 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
116 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringFileBuffers;
117 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
118 import org.eclipse.jdt.internal.corext.refactoring.util.TextEditBasedChangeManager;
119 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
120 import org.eclipse.jdt.internal.corext.util.JdtFlags;
121 import org.eclipse.jdt.internal.corext.util.Messages;
122 import org.eclipse.jdt.internal.corext.util.Strings;
123
124 import org.eclipse.jdt.ui.CodeGeneration;
125 import org.eclipse.jdt.ui.JavaElementLabels;
126
127 import org.eclipse.jdt.internal.ui.JavaPlugin;
128 import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
129
130 /**
131  * Refactoring processor to extract interfaces.
132  */

133 public final class ExtractInterfaceProcessor extends SuperTypeRefactoringProcessor {
134
135     private static final String JavaDoc ATTRIBUTE_ABSTRACT= "abstract"; //$NON-NLS-1$
136

137     private static final String JavaDoc ATTRIBUTE_COMMENTS= "comments"; //$NON-NLS-1$
138

139     private static final String JavaDoc ATTRIBUTE_PUBLIC= "public"; //$NON-NLS-1$
140

141     /** The identifier of this processor */
142     public static final String JavaDoc IDENTIFIER= "org.eclipse.jdt.ui.extractInterfaceProcessor"; //$NON-NLS-1$
143

144     /** The extract interface group category set */
145     private static final GroupCategorySet SET_EXTRACT_INTERFACE= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.extractInterface", //$NON-NLS-1$
146
RefactoringCoreMessages.ExtractInterfaceProcessor_category_name, RefactoringCoreMessages.ExtractInterfaceProcessor_category_description));
147
148     /**
149      * Is the specified member extractable from the type?
150      *
151      * @param member
152      * the member to test
153      * @return <code>true</code> if the member is extractable,
154      * <code>false</code> otherwise
155      * @throws JavaModelException
156      * if an error occurs
157      */

158     protected static boolean isExtractableMember(final IMember member) throws JavaModelException {
159         Assert.isNotNull(member);
160         switch (member.getElementType()) {
161             case IJavaElement.METHOD:
162                 return JdtFlags.isPublic(member) && !JdtFlags.isStatic(member) && !((IMethod) member).isConstructor();
163             case IJavaElement.FIELD:
164                 return JdtFlags.isPublic(member) && JdtFlags.isStatic(member) && JdtFlags.isFinal(member) && !JdtFlags.isEnum(member);
165             default:
166                 return false;
167         }
168     }
169
170     /** Should extracted methods be declared as abstract? */
171     private boolean fAbstract= true;
172
173     /** The text edit based change manager */
174     private TextEditBasedChangeManager fChangeManager= null;
175
176     /** Should comments be generated? */
177     private boolean fComments= true;
178
179     /** The members to extract */
180     private IMember[] fMembers= null;
181
182     /** Should extracted methods be declared as public? */
183     private boolean fPublic= true;
184
185     /** The subtype where to extract the supertype */
186     private IType fSubType;
187
188     /** The supertype name */
189     private String JavaDoc fSuperName;
190
191     /** The source of the new supertype */
192     private String JavaDoc fSuperSource= null;
193
194     /**
195      * Creates a new extract interface processor.
196      *
197      * @param type
198      * the type where to extract the supertype, or <code>null</code>
199      * if invoked by scripting
200      * @param settings
201      * the code generation settings, or <code>null</code> if
202      * invoked by scripting
203      */

204     public ExtractInterfaceProcessor(final IType type, final CodeGenerationSettings settings) {
205         super(settings);
206         fSubType= type;
207         if (fSubType != null)
208             fSuperName= fSubType.getElementName();
209     }
210
211     /*
212      * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#checkFinalConditions(org.eclipse.core.runtime.IProgressMonitor,org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext)
213      */

214     public final RefactoringStatus checkFinalConditions(final IProgressMonitor monitor, final CheckConditionsContext context) throws CoreException, OperationCanceledException {
215         Assert.isNotNull(monitor);
216         Assert.isNotNull(context);
217         final RefactoringStatus status= new RefactoringStatus();
218         fChangeManager= new TextEditBasedChangeManager();
219         try {
220             monitor.beginTask("", 1); //$NON-NLS-1$
221
monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_checking);
222             status.merge(Checks.checkIfCuBroken(fSubType));
223             if (!status.hasError()) {
224                 if (fSubType.isBinary() || fSubType.isReadOnly() || !fSubType.exists())
225                     status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_no_binary, JavaStatusContext.create(fSubType)));
226                 else if (fSubType.isAnonymous())
227                     status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_no_anonymous, JavaStatusContext.create(fSubType)));
228                 else if (fSubType.isAnnotation())
229                     status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_no_annotation, JavaStatusContext.create(fSubType)));
230                 else {
231                     status.merge(checkSuperType());
232                     if (!status.hasFatalError()) {
233                         if (!status.hasFatalError()) {
234                             fChangeManager= createChangeManager(new SubProgressMonitor(monitor, 1), status);
235                             if (!status.hasFatalError()) {
236                                 final RefactoringStatus validation= Checks.validateModifiesFiles(ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits()), getRefactoring().getValidationContext());
237                                 if (!validation.isOK())
238                                     return validation;
239                             }
240                         }
241                     }
242                 }
243             }
244         } finally {
245             monitor.done();
246         }
247         return status;
248     }
249
250     /*
251      * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#checkInitialConditions(org.eclipse.core.runtime.IProgressMonitor)
252      */

253     public final RefactoringStatus checkInitialConditions(final IProgressMonitor monitor) throws CoreException, OperationCanceledException {
254         Assert.isNotNull(monitor);
255         final RefactoringStatus status= new RefactoringStatus();
256         try {
257             monitor.beginTask("", 1); //$NON-NLS-1$
258
monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_checking);
259             status.merge(Checks.checkIfCuBroken(fSubType));
260             monitor.worked(1);
261         } finally {
262             monitor.done();
263         }
264         return status;
265     }
266
267     /**
268      * Checks whether the supertype clashes with existing types.
269      *
270      * @return the status of the condition checking
271      * @throws JavaModelException
272      * if an error occurs
273      */

274     protected final RefactoringStatus checkSuperType() throws JavaModelException {
275         final IPackageFragment fragment= fSubType.getPackageFragment();
276         final IType type= Checks.findTypeInPackage(fragment, fSuperName);
277         if (type != null && type.exists()) {
278             if (fragment.isDefaultPackage())
279                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_existing_default_type, new String JavaDoc[] { fSuperName }));
280             else
281                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_existing_type, new String JavaDoc[] { fSuperName, fragment.getElementName() }));
282         }
283         return new RefactoringStatus();
284     }
285
286     /**
287      * Checks whether the type name is valid.
288      *
289      * @param name
290      * the name to check
291      * @return the status of the condition checking
292      */

293     public final RefactoringStatus checkTypeName(final String JavaDoc name) {
294         Assert.isNotNull(name);
295         try {
296             final RefactoringStatus result= Checks.checkTypeName(name);
297             if (result.hasFatalError())
298                 return result;
299             final String JavaDoc unitName= JavaModelUtil.getRenamedCUName(fSubType.getCompilationUnit(), name);
300             result.merge(Checks.checkCompilationUnitName(unitName));
301             if (result.hasFatalError())
302                 return result;
303             final IPackageFragment fragment= fSubType.getPackageFragment();
304             if (fragment.getCompilationUnit(unitName).exists()) {
305                 result.addFatalError(Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_existing_compilation_unit, new String JavaDoc[] { unitName, fragment.getElementName() }));
306                 return result;
307             }
308             result.merge(checkSuperType());
309             return result;
310         } catch (JavaModelException exception) {
311             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error);
312         }
313     }
314
315     /*
316      * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#createChange(org.eclipse.core.runtime.IProgressMonitor)
317      */

318     public final Change createChange(final IProgressMonitor monitor) throws CoreException, OperationCanceledException {
319         Assert.isNotNull(monitor);
320         try {
321             monitor.beginTask("", 1); //$NON-NLS-1$
322
monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating);
323             final Map JavaDoc arguments= new HashMap JavaDoc();
324             String JavaDoc project= null;
325             final IJavaProject javaProject= fSubType.getJavaProject();
326             if (javaProject != null)
327                 project= javaProject.getElementName();
328             int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE;
329             try {
330                 if (fSubType.isLocal() || fSubType.isAnonymous())
331                     flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
332             } catch (JavaModelException exception) {
333                 JavaPlugin.log(exception);
334             }
335             final IPackageFragment fragment= fSubType.getPackageFragment();
336             final ICompilationUnit cu= fragment.getCompilationUnit(JavaModelUtil.getRenamedCUName(fSubType.getCompilationUnit(), fSuperName));
337             final IType type= cu.getType(fSuperName);
338             final String JavaDoc description= Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_description_descriptor_short, fSuperName);
339             final String JavaDoc header= Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_descriptor_description, new String JavaDoc[] { JavaElementLabels.getElementLabel(type, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(fSubType, JavaElementLabels.ALL_FULLY_QUALIFIED) });
340             final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header);
341             comment.addSetting(Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_refactored_element_pattern, JavaElementLabels.getElementLabel(type, JavaElementLabels.ALL_FULLY_QUALIFIED)));
342             final String JavaDoc[] settings= new String JavaDoc[fMembers.length];
343             for (int index= 0; index < settings.length; index++)
344                 settings[index]= JavaElementLabels.getElementLabel(fMembers[index], JavaElementLabels.ALL_FULLY_QUALIFIED);
345             comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ExtractInterfaceProcessor_extracted_members_pattern, settings));
346             addSuperTypeSettings(comment, true);
347             final JDTRefactoringDescriptor descriptor= new JDTRefactoringDescriptor(IJavaRefactorings.EXTRACT_INTERFACE, project, description, comment.asString(), arguments, flags);
348             arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_INPUT, descriptor.elementToHandle(fSubType));
349             arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_NAME, fSuperName);
350             for (int index= 0; index < fMembers.length; index++)
351                 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + (index + 1), descriptor.elementToHandle(fMembers[index]));
352             arguments.put(ATTRIBUTE_ABSTRACT, Boolean.valueOf(fAbstract).toString());
353             arguments.put(ATTRIBUTE_COMMENTS, Boolean.valueOf(fComments).toString());
354             arguments.put(ATTRIBUTE_PUBLIC, Boolean.valueOf(fPublic).toString());
355             arguments.put(ATTRIBUTE_REPLACE, Boolean.valueOf(fReplace).toString());
356             arguments.put(ATTRIBUTE_INSTANCEOF, Boolean.valueOf(fInstanceOf).toString());
357             final DynamicValidationRefactoringChange change= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.ExtractInterfaceRefactoring_name, fChangeManager.getAllChanges());
358             final IFile file= ResourceUtil.getFile(fSubType.getCompilationUnit());
359             if (fSuperSource != null && fSuperSource.length() > 0)
360                 change.add(new CreateCompilationUnitChange(fSubType.getPackageFragment().getCompilationUnit(JavaModelUtil.getRenamedCUName(fSubType.getCompilationUnit(), fSuperName)), fSuperSource, file.getCharset(false)));
361             monitor.worked(1);
362             return change;
363         } finally {
364             monitor.done();
365         }
366     }
367
368     /**
369      * Creates the text change manager for this processor.
370      *
371      * @param monitor
372      * the progress monitor to display progress
373      * @param status
374      * the refactoring status
375      * @return the created text change manager
376      * @throws JavaModelException
377      * if the method declaration could not be found
378      * @throws CoreException
379      * if the changes could not be generated
380      */

381     protected final TextEditBasedChangeManager createChangeManager(final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException, CoreException {
382         Assert.isNotNull(status);
383         Assert.isNotNull(monitor);
384         try {
385             monitor.beginTask("", 300); //$NON-NLS-1$
386
monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating);
387             resetEnvironment();
388             final TextEditBasedChangeManager manager= new TextEditBasedChangeManager();
389             final CompilationUnitRewrite sourceRewrite= new CompilationUnitRewrite(fSubType.getCompilationUnit());
390             final AbstractTypeDeclaration declaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(fSubType, sourceRewrite.getRoot());
391             if (declaration != null) {
392                 createTypeSignature(sourceRewrite, declaration, status, new SubProgressMonitor(monitor, 20));
393                 final IField[] fields= getExtractedFields(fSubType.getCompilationUnit());
394                 if (fields.length > 0)
395                     ASTNodeDeleteUtil.markAsDeleted(fields, sourceRewrite, sourceRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_remove_field_label, SET_EXTRACT_INTERFACE));
396                 if (fSubType.isInterface()) {
397                     final IMethod[] methods= getExtractedMethods(fSubType.getCompilationUnit());
398                     if (methods.length > 0)
399                         ASTNodeDeleteUtil.markAsDeleted(methods, sourceRewrite, sourceRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_remove_method_label, SET_EXTRACT_INTERFACE));
400                 }
401                 final String JavaDoc name= JavaModelUtil.getRenamedCUName(fSubType.getCompilationUnit(), fSuperName);
402                 final ICompilationUnit original= fSubType.getPackageFragment().getCompilationUnit(name);
403                 final ICompilationUnit copy= getSharedWorkingCopy(original.getPrimary(), new SubProgressMonitor(monitor, 20));
404                 fSuperSource= createTypeSource(copy, fSubType, fSuperName, sourceRewrite, declaration, status, new SubProgressMonitor(monitor, 40));
405                 if (fSuperSource != null) {
406                     copy.getBuffer().setContents(fSuperSource);
407                     JavaModelUtil.reconcile(copy);
408                 }
409                 final Set JavaDoc replacements= new HashSet JavaDoc();
410                 if (fReplace)
411                     rewriteTypeOccurrences(manager, sourceRewrite, copy, replacements, status, new SubProgressMonitor(monitor, 220));
412                 createMethodComments(sourceRewrite, replacements);
413                 manager.manage(fSubType.getCompilationUnit(), sourceRewrite.createChange());
414             }
415             return manager;
416         } finally {
417             monitor.done();
418         }
419     }
420
421     /*
422      * @see org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeRefactoringProcessor#createContraintSolver(org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsModel)
423      */

424     protected final SuperTypeConstraintsSolver createContraintSolver(final SuperTypeConstraintsModel model) {
425         return new ExtractInterfaceConstraintsSolver(model, fSuperName);
426     }
427
428     /**
429      * Creates a target field declaration.
430      *
431      * @param sourceRewrite
432      * the source compilation unit rewrite
433      * @param targetRewrite
434      * the target rewrite
435      * @param targetDeclaration
436      * the target type declaration
437      * @param fragment
438      * the source variable declaration fragment
439      * @throws CoreException
440      * if a buffer could not be retrieved
441      */

442     protected final void createFieldDeclaration(final CompilationUnitRewrite sourceRewrite, final ASTRewrite targetRewrite, final AbstractTypeDeclaration targetDeclaration, final VariableDeclarationFragment fragment) throws CoreException {
443         Assert.isNotNull(targetDeclaration);
444         Assert.isNotNull(sourceRewrite);
445         Assert.isNotNull(targetRewrite);
446         Assert.isNotNull(fragment);
447         final FieldDeclaration field= (FieldDeclaration) fragment.getParent();
448         ImportRewriteUtil.collectImports(fSubType.getJavaProject(), field, fTypeBindings, fStaticBindings, false);
449         final ASTRewrite rewrite= ASTRewrite.create(field.getAST());
450         final ITrackedNodePosition position= rewrite.track(field);
451         final ListRewrite rewriter= rewrite.getListRewrite(field, FieldDeclaration.FRAGMENTS_PROPERTY);
452         VariableDeclarationFragment current= null;
453         for (final Iterator JavaDoc iterator= field.fragments().iterator(); iterator.hasNext();) {
454             current= (VariableDeclarationFragment) iterator.next();
455             if (!current.getName().getIdentifier().equals(fragment.getName().getIdentifier()))
456                 rewriter.remove(current, null);
457         }
458         final ICompilationUnit unit= sourceRewrite.getCu();
459         final ITextFileBuffer buffer= RefactoringFileBuffers.acquire(unit);
460         try {
461             final IDocument document= new Document(buffer.getDocument().get());
462             try {
463                 rewrite.rewriteAST(document, unit.getJavaProject().getOptions(true)).apply(document, TextEdit.UPDATE_REGIONS);
464                 targetRewrite.getListRewrite(targetDeclaration, targetDeclaration.getBodyDeclarationsProperty()).insertFirst(targetRewrite.createStringPlaceholder(normalizeText(document.get(position.getStartPosition(), position.getLength())), ASTNode.FIELD_DECLARATION), null);
465             } catch (MalformedTreeException exception) {
466                 JavaPlugin.log(exception);
467             } catch (BadLocationException exception) {
468                 JavaPlugin.log(exception);
469             }
470         } finally {
471             RefactoringFileBuffers.release(unit);
472         }
473     }
474
475     /**
476      * {@inheritDoc}
477      */

478     protected final void createMemberDeclarations(final CompilationUnitRewrite sourceRewrite, final ASTRewrite targetRewrite, final AbstractTypeDeclaration targetDeclaration) throws CoreException {
479         Assert.isNotNull(sourceRewrite);
480         Assert.isNotNull(targetRewrite);
481         Assert.isNotNull(targetDeclaration);
482         Arrays.sort(fMembers, new Comparator JavaDoc() {
483
484             public final int compare(final Object JavaDoc first, final Object JavaDoc second) {
485                 Assert.isNotNull(first);
486                 Assert.isNotNull(second);
487                 final ISourceReference predecessor= (ISourceReference) first;
488                 final ISourceReference successor= (ISourceReference) second;
489                 try {
490                     return predecessor.getSourceRange().getOffset() - successor.getSourceRange().getOffset();
491                 } catch (JavaModelException exception) {
492                     return first.hashCode() - second.hashCode();
493                 }
494             }
495         });
496         fTypeBindings.clear();
497         fStaticBindings.clear();
498         if (fMembers.length > 0) {
499             IMember member= null;
500             for (int index= fMembers.length - 1; index >= 0; index--) {
501                 member= fMembers[index];
502                 if (member instanceof IField) {
503                     createFieldDeclaration(sourceRewrite, targetRewrite, targetDeclaration, ASTNodeSearchUtil.getFieldDeclarationFragmentNode((IField) member, sourceRewrite.getRoot()));
504                 } else if (member instanceof IMethod) {
505                     createMethodDeclaration(sourceRewrite, targetRewrite, targetDeclaration, ASTNodeSearchUtil.getMethodDeclarationNode((IMethod) member, sourceRewrite.getRoot()));
506                 }
507             }
508         }
509     }
510
511     /**
512      * Creates the method comment for the specified declaration.
513      *
514      * @param sourceRewrite
515      * the compilation unit rewrite
516      * @param declaration
517      * the method declaration
518      * @param replacements
519      * the set of variable binding keys of formal parameters which
520      * must be replaced
521      * @param javadoc
522      * <code>true</code> if javadoc comments are processed,
523      * <code>false</code> otherwise
524      * @throws CoreException
525      * if an error occurs
526      */

527     protected final void createMethodComment(final CompilationUnitRewrite sourceRewrite, final MethodDeclaration declaration, final Set JavaDoc replacements, final boolean javadoc) throws CoreException {
528         Assert.isNotNull(sourceRewrite);
529         Assert.isNotNull(declaration);
530         Assert.isNotNull(replacements);
531         final IMethodBinding binding= declaration.resolveBinding();
532         if (binding != null) {
533             IVariableBinding variable= null;
534             SingleVariableDeclaration argument= null;
535             final IPackageFragment fragment= fSubType.getPackageFragment();
536             final String JavaDoc string= fragment.isDefaultPackage() ? fSuperName : fragment.getElementName() + "." + fSuperName; //$NON-NLS-1$
537
final ITypeBinding[] bindings= binding.getParameterTypes();
538             final String JavaDoc[] names= new String JavaDoc[bindings.length];
539             for (int offset= 0; offset < names.length; offset++) {
540                 argument= (SingleVariableDeclaration) declaration.parameters().get(offset);
541                 variable= argument.resolveBinding();
542                 if (variable != null) {
543                     if (replacements.contains(variable.getKey()))
544                         names[offset]= string;
545                     else {
546                         if (binding.isVarargs() && bindings[offset].isArray() && offset == names.length - 1)
547                             names[offset]= Bindings.getFullyQualifiedName(bindings[offset].getElementType());
548                         else
549                             names[offset]= Bindings.getFullyQualifiedName(bindings[offset]);
550                     }
551                 }
552             }
553             final String JavaDoc comment= CodeGeneration.getMethodComment(fSubType.getCompilationUnit(), fSubType.getElementName(), declaration, false, binding.getName(), string, names, StubUtility.getLineDelimiterUsed(fSubType.getJavaProject()));
554             if (comment != null) {
555                 final ASTRewrite rewrite= sourceRewrite.getASTRewrite();
556                 if (declaration.getJavadoc() != null) {
557                     rewrite.replace(declaration.getJavadoc(), rewrite.createStringPlaceholder(comment, ASTNode.JAVADOC), sourceRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_rewrite_comment, SET_EXTRACT_INTERFACE));
558                 } else if (javadoc) {
559                     rewrite.set(declaration, MethodDeclaration.JAVADOC_PROPERTY, rewrite.createStringPlaceholder(comment, ASTNode.JAVADOC), sourceRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_add_comment, SET_EXTRACT_INTERFACE));
560                 }
561             }
562         }
563     }
564
565     /**
566      * Creates the method annotations and comments of the extracted methods in
567      * the source type.
568      *
569      * @param sourceRewrite
570      * the source compilation unit rewrite
571      * @param replacements
572      * the set of variable binding keys of formal parameters which
573      * must be replaced
574      * @throws CoreException
575      * if an error occurs
576      */

577     protected final void createMethodComments(final CompilationUnitRewrite sourceRewrite, final Set JavaDoc replacements) throws CoreException {
578         Assert.isNotNull(sourceRewrite);
579         Assert.isNotNull(replacements);
580         if (fComments && fMembers.length > 0) {
581             final IJavaProject project= fSubType.getJavaProject();
582             final boolean javadoc= project.getOption(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, true).equals(JavaCore.ENABLED);
583             IMember member= null;
584             for (int index= 0; index < fMembers.length; index++) {
585                 member= fMembers[index];
586                 if (member instanceof IMethod)
587                     createMethodComment(sourceRewrite, ASTNodeSearchUtil.getMethodDeclarationNode((IMethod) member, sourceRewrite.getRoot()), replacements, javadoc);
588             }
589         }
590     }
591
592     /**
593      * Creates a target method declaration.
594      *
595      * @param sourceRewrite
596      * the source compilation unit rewrite
597      * @param targetRewrite
598      * the target rewrite
599      * @param targetDeclaration
600      * the target type declaration
601      * @param declaration
602      * the source method declaration
603      * @throws CoreException
604      * if a buffer could not be retrieved
605      */

606     protected final void createMethodDeclaration(final CompilationUnitRewrite sourceRewrite, final ASTRewrite targetRewrite, final AbstractTypeDeclaration targetDeclaration, final MethodDeclaration declaration) throws CoreException {
607         Assert.isNotNull(targetDeclaration);
608         Assert.isNotNull(sourceRewrite);
609         Assert.isNotNull(targetRewrite);
610         Assert.isNotNull(declaration);
611         ImportRewriteUtil.collectImports(fSubType.getJavaProject(), declaration, fTypeBindings, fStaticBindings, true);
612         final ASTRewrite rewrite= ASTRewrite.create(declaration.getAST());
613         final ITrackedNodePosition position= rewrite.track(declaration);
614         if (declaration.getBody() != null)
615             rewrite.remove(declaration.getBody(), null);
616         final ListRewrite list= rewrite.getListRewrite(declaration, declaration.getModifiersProperty());
617         boolean publicFound= false;
618         boolean abstractFound= false;
619         ITypeBinding binding= null;
620         Modifier modifier= null;
621         Annotation annotation= null;
622         IExtendedModifier extended= null;
623         for (final Iterator JavaDoc iterator= declaration.modifiers().iterator(); iterator.hasNext();) {
624             extended= (IExtendedModifier) iterator.next();
625             if (!extended.isAnnotation()) {
626                 modifier= (Modifier) extended;
627                 if (fPublic && modifier.getKeyword().equals(Modifier.ModifierKeyword.PUBLIC_KEYWORD)) {
628                     publicFound= true;
629                     continue;
630                 }
631                 if (fAbstract && modifier.getKeyword().equals(Modifier.ModifierKeyword.ABSTRACT_KEYWORD)) {
632                     abstractFound= true;
633                     continue;
634                 }
635                 list.remove(modifier, null);
636             } else if (extended.isAnnotation()) {
637                 annotation= (Annotation) extended;
638                 binding= annotation.resolveTypeBinding();
639                 if (binding.getQualifiedName().equals("java.lang.Override")) //$NON-NLS-1$
640
list.remove(annotation, null);
641             }
642         }
643         final ModifierRewrite rewriter= ModifierRewrite.create(rewrite, declaration);
644         if (fPublic && !publicFound)
645             rewriter.setVisibility(Modifier.PUBLIC, null);
646         if (fAbstract && !abstractFound)
647             rewriter.setModifiers(Modifier.ABSTRACT, 0, null);
648         final ICompilationUnit unit= sourceRewrite.getCu();
649         final ITextFileBuffer buffer= RefactoringFileBuffers.acquire(unit);
650         try {
651             final IDocument document= new Document(buffer.getDocument().get());
652             try {
653                 rewrite.rewriteAST(document, unit.getJavaProject().getOptions(true)).apply(document, TextEdit.UPDATE_REGIONS);
654                 targetRewrite.getListRewrite(targetDeclaration, targetDeclaration.getBodyDeclarationsProperty()).insertFirst(targetRewrite.createStringPlaceholder(normalizeText(document.get(position.getStartPosition(), position.getLength())), ASTNode.METHOD_DECLARATION), null);
655             } catch (MalformedTreeException exception) {
656                 JavaPlugin.log(exception);
657             } catch (BadLocationException exception) {
658                 JavaPlugin.log(exception);
659             }
660         } finally {
661             RefactoringFileBuffers.release(unit);
662         }
663     }
664
665     /**
666      * Creates the new signature of the source type.
667      *
668      * @param rewrite
669      * the source compilation unit rewrite
670      * @param declaration
671      * the type declaration
672      * @param status
673      * the refactoring status
674      * @param monitor
675      * the progress monitor to use
676      * @throws JavaModelException
677      * if the type parameters cannot be retrieved
678      */

679     protected final void createTypeSignature(final CompilationUnitRewrite rewrite, final AbstractTypeDeclaration declaration, final RefactoringStatus status, final IProgressMonitor monitor) throws JavaModelException {
680         Assert.isNotNull(rewrite);
681         Assert.isNotNull(declaration);
682         Assert.isNotNull(status);
683         Assert.isNotNull(monitor);
684         try {
685             monitor.beginTask("", 1); //$NON-NLS-1$
686
monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating);
687             final AST ast= declaration.getAST();
688             final ITypeParameter[] parameters= fSubType.getTypeParameters();
689             Type type= ast.newSimpleType(ast.newSimpleName(fSuperName));
690             if (parameters.length > 0) {
691                 final ParameterizedType parameterized= ast.newParameterizedType(type);
692                 for (int index= 0; index < parameters.length; index++)
693                     parameterized.typeArguments().add(ast.newSimpleType(ast.newSimpleName(parameters[index].getElementName())));
694                 type= parameterized;
695             }
696             final ASTRewrite rewriter= rewrite.getASTRewrite();
697             if (declaration instanceof TypeDeclaration)
698                 rewriter.getListRewrite(declaration, TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY).insertLast(type, rewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_add_super_interface, SET_EXTRACT_INTERFACE));
699             else if (declaration instanceof EnumDeclaration)
700                 rewriter.getListRewrite(declaration, EnumDeclaration.SUPER_INTERFACE_TYPES_PROPERTY).insertLast(type, rewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_add_super_interface, SET_EXTRACT_INTERFACE));
701             monitor.worked(1);
702         } finally {
703             monitor.done();
704         }
705     }
706
707     /**
708      * Should extracted methods be declared as abstract?
709      *
710      * @return <code>true</code> if the should be declared as abstract,
711      * <code>false</code> otherwise
712      */

713     public final boolean getAbstract() {
714         return fAbstract;
715     }
716
717     /*
718      * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getElements()
719      */

720     public final Object JavaDoc[] getElements() {
721         return new Object JavaDoc[] { fSubType };
722     }
723
724     /**
725      * Returns the list of extractable members from the type.
726      *
727      * @return the list of extractable members
728      * @throws JavaModelException
729      * if an error occurs
730      */

731     public final IMember[] getExtractableMembers() throws JavaModelException {
732         final List JavaDoc list= new ArrayList JavaDoc();
733         IJavaElement[] children= fSubType.getChildren();
734         for (int index= 0; index < children.length; index++) {
735             if (children[index] instanceof IMember && isExtractableMember((IMember) children[index]))
736                 list.add(children[index]);
737         }
738         final IMember[] members= new IMember[list.size()];
739         list.toArray(members);
740         return members;
741     }
742
743     /**
744      * Returns the extracted fields from the compilation unit.
745      *
746      * @param unit
747      * the compilation unit
748      * @return the extracted fields
749      */

750     protected final IField[] getExtractedFields(final ICompilationUnit unit) {
751         Assert.isNotNull(unit);
752         final List JavaDoc list= new ArrayList JavaDoc();
753         for (int index= 0; index < fMembers.length; index++) {
754             if (fMembers[index] instanceof IField) {
755                 final IJavaElement element= JavaModelUtil.findInCompilationUnit(unit, fMembers[index]);
756                 if (element instanceof IField)
757                     list.add(element);
758             }
759         }
760         final IField[] fields= new IField[list.size()];
761         list.toArray(fields);
762         return fields;
763     }
764
765     /**
766      * Returns the extracted methods from the compilation unit.
767      *
768      * @param unit
769      * the compilation unit
770      * @return the extracted methods
771      */

772     protected final IMethod[] getExtractedMethods(final ICompilationUnit unit) {
773         Assert.isNotNull(unit);
774         final List JavaDoc list= new ArrayList JavaDoc();
775         for (int index= 0; index < fMembers.length; index++) {
776             if (fMembers[index] instanceof IMethod) {
777                 final IJavaElement element= JavaModelUtil.findInCompilationUnit(unit, fMembers[index]);
778                 if (element instanceof IMethod)
779                     list.add(element);
780             }
781         }
782         final IMethod[] methods= new IMethod[list.size()];
783         list.toArray(methods);
784         return methods;
785     }
786
787     /*
788      * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getIdentifier()
789      */

790     public final String JavaDoc getIdentifier() {
791         return IDENTIFIER;
792     }
793
794     /*
795      * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getProcessorName()
796      */

797     public final String JavaDoc getProcessorName() {
798         return RefactoringCoreMessages.ExtractInterfaceProcessor_name;
799     }
800
801     /**
802      * Should extracted methods be declared as public?
803      *
804      * @return <code>true</code> if the should be declared as public,
805      * <code>false</code> otherwise
806      */

807     public final boolean getPublic() {
808         return fPublic;
809     }
810
811     /**
812      * Returns the type where to extract an interface.
813      *
814      * @return the type where to extract an interface
815      */

816     public final IType getType() {
817         return fSubType;
818     }
819
820     /**
821      * Returns the new interface name.
822      *
823      * @return the new interface name
824      */

825     public final String JavaDoc getTypeName() {
826         return fSuperName;
827     }
828
829     /**
830      * {@inheritDoc}
831      */

832     public final RefactoringStatus initialize(final RefactoringArguments arguments) {
833         if (arguments instanceof JavaRefactoringArguments) {
834             final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments;
835             String JavaDoc handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT);
836             if (handle != null) {
837                 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
838                 if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE)
839                     return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.EXTRACT_INTERFACE);
840                 else
841                     fSubType= (IType) element;
842             } else
843                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT));
844             final String JavaDoc name= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME);
845             if (name != null) {
846                 fSuperName= name;
847                 final RefactoringStatus status= checkTypeName(name);
848                 if (status.hasError())
849                     return status;
850             } else
851                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_NAME));
852             final String JavaDoc deferred= extended.getAttribute(ATTRIBUTE_ABSTRACT);
853             if (deferred != null) {
854                 fAbstract= Boolean.valueOf(deferred).booleanValue();
855             } else
856                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_ABSTRACT));
857             final String JavaDoc comment= extended.getAttribute(ATTRIBUTE_COMMENTS);
858             if (comment != null) {
859                 fComments= Boolean.valueOf(comment).booleanValue();
860             } else
861                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_COMMENTS));
862             final String JavaDoc instance= extended.getAttribute(ATTRIBUTE_INSTANCEOF);
863             if (instance != null) {
864                 fInstanceOf= Boolean.valueOf(instance).booleanValue();
865             } else
866                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_INSTANCEOF));
867             final String JavaDoc visibility= extended.getAttribute(ATTRIBUTE_PUBLIC);
868             if (visibility != null) {
869                 fPublic= Boolean.valueOf(visibility).booleanValue();
870             } else
871                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_PUBLIC));
872             final String JavaDoc replace= extended.getAttribute(ATTRIBUTE_REPLACE);
873             if (replace != null) {
874                 fReplace= Boolean.valueOf(replace).booleanValue();
875             } else
876                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_REPLACE));
877             int count= 1;
878             final List JavaDoc elements= new ArrayList JavaDoc();
879             String JavaDoc attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + count;
880             final RefactoringStatus status= new RefactoringStatus();
881             while ((handle= extended.getAttribute(attribute)) != null) {
882                 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
883                 if (element == null || !element.exists())
884                     status.merge(ScriptableRefactoring.createInputWarningStatus(element, getRefactoring().getName(), IJavaRefactorings.EXTRACT_INTERFACE));
885                 else
886                     elements.add(element);
887                 count++;
888                 attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + count;
889             }
890             fMembers= (IMember[]) elements.toArray(new IMember[elements.size()]);
891             fSettings= JavaPreferencesSettings.getCodeGenerationSettings(fSubType.getJavaProject());
892             if (!status.isOK())
893                 return status;
894         } else
895             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
896         return new RefactoringStatus();
897     }
898
899     /*
900      * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#isApplicable()
901      */

902     public final boolean isApplicable() throws CoreException {
903         return Checks.isAvailable(fSubType) && !fSubType.isBinary() && !fSubType.isReadOnly() && !fSubType.isAnnotation() && !fSubType.isAnonymous();
904     }
905
906     /**
907      * Should comments be generated?
908      *
909      * @return <code>true</code> if comments should be generated,
910      * <code>false</code> otherwise
911      */

912     public final boolean isComments() {
913         return fComments;
914     }
915
916     /*
917      * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#loadParticipants(org.eclipse.ltk.core.refactoring.RefactoringStatus,org.eclipse.ltk.core.refactoring.participants.SharableParticipants)
918      */

919     public final RefactoringParticipant[] loadParticipants(final RefactoringStatus status, final SharableParticipants sharedParticipants) throws CoreException {
920         return new RefactoringParticipant[0];
921     }
922
923     /**
924      * Normalizes the indentation of the specified text.
925      *
926      * @param code
927      * the text to normalize
928      * @return the normalized text
929      * @throws JavaModelException
930      * if an error occurs
931      */

932     protected final String JavaDoc normalizeText(final String JavaDoc code) throws JavaModelException {
933         Assert.isNotNull(code);
934         final String JavaDoc[] lines= Strings.convertIntoLines(code);
935         final IJavaProject project= fSubType.getJavaProject();
936         Strings.trimIndentation(lines, project, false);
937         return Strings.concatenate(lines, StubUtility.getLineDelimiterUsed(project));
938     }
939
940     /**
941      * Resets the environment.
942      */

943     protected void resetEnvironment() {
944         fSuperSource= null;
945         resetWorkingCopies();
946     }
947
948     /**
949      * {@inheritDoc}
950      */

951     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 {
952         try {
953             monitor.beginTask("", 100); //$NON-NLS-1$
954
monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating);
955             CompilationUnitRewrite currentRewrite= null;
956             final boolean isSubUnit= rewrite.getCu().equals(unit.getPrimary());
957             if (isSubUnit)
958                 currentRewrite= rewrite;
959             else
960                 currentRewrite= new CompilationUnitRewrite(unit, node);
961             final Collection JavaDoc collection= (Collection JavaDoc) fTypeOccurrences.get(unit);
962             if (collection != null && !collection.isEmpty()) {
963                 final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 100);
964                 try {
965                     subMonitor.beginTask("", collection.size() * 10); //$NON-NLS-1$
966
subMonitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating);
967                     TType estimate= null;
968                     ISourceConstraintVariable variable= null;
969                     ITypeConstraintVariable constraint= null;
970                     for (final Iterator JavaDoc iterator= collection.iterator(); iterator.hasNext();) {
971                         variable= (ISourceConstraintVariable) iterator.next();
972                         if (variable instanceof ITypeConstraintVariable) {
973                             constraint= (ITypeConstraintVariable) variable;
974                             estimate= (TType) constraint.getData(SuperTypeConstraintsSolver.DATA_TYPE_ESTIMATE);
975                             if (estimate != null) {
976                                 final CompilationUnitRange range= constraint.getRange();
977                                 if (isSubUnit)
978                                     rewriteTypeOccurrence(range, estimate, requestor, currentRewrite, node, replacements, currentRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.SuperTypeRefactoringProcessor_update_type_occurrence, SET_SUPER_TYPE));
979                                 else {
980                                     final ASTNode result= NodeFinder.perform(node, range.getSourceRange());
981                                     if (result != null)
982                                         rewriteTypeOccurrence(estimate, currentRewrite, result, currentRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.SuperTypeRefactoringProcessor_update_type_occurrence, SET_SUPER_TYPE));
983                                 }
984                                 subMonitor.worked(10);
985                             }
986                         }
987                     }
988                 } finally {
989                     subMonitor.done();
990                 }
991             }
992             if (!isSubUnit) {
993                 final TextChange change= currentRewrite.createChange();
994                 if (change != null)
995                     manager.manage(unit, change);
996             }
997         } finally {
998             monitor.done();
999         }
1000    }
1001
1002    /**
1003     * Creates the necessary text edits to replace the subtype occurrences by a
1004     * supertype.
1005     *
1006     * @param manager
1007     * the text change manager
1008     * @param sourceRewrite
1009     * the compilation unit of the subtype (not in working copy mode)
1010     * @param superUnit
1011     * the compilation unit of the supertype (in working copy mode)
1012     * @param replacements
1013     * the set of variable binding keys of formal parameters which
1014     * must be replaced
1015     * @param status
1016     * the refactoring status
1017     * @param monitor
1018     * the progress monitor to display progress
1019     * @throws CoreException
1020     * if an error occurs
1021     */

1022    protected final void rewriteTypeOccurrences(final TextEditBasedChangeManager manager, final CompilationUnitRewrite sourceRewrite, final ICompilationUnit superUnit, final Set JavaDoc replacements, final RefactoringStatus status, final IProgressMonitor monitor) throws CoreException {
1023        Assert.isNotNull(manager);
1024        Assert.isNotNull(sourceRewrite);
1025        Assert.isNotNull(superUnit);
1026        Assert.isNotNull(replacements);
1027        Assert.isNotNull(status);
1028        Assert.isNotNull(monitor);
1029        try {
1030            monitor.beginTask("", 300); //$NON-NLS-1$
1031
monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating);
1032            final ICompilationUnit subUnit= getSharedWorkingCopy(fSubType.getCompilationUnit().getPrimary(), new SubProgressMonitor(monitor, 20));
1033            final ITextFileBuffer buffer= RefactoringFileBuffers.acquire(fSubType.getCompilationUnit());
1034            final ASTRewrite rewrite= sourceRewrite.getASTRewrite();
1035            try {
1036                final IDocument document= new Document(buffer.getDocument().get());
1037                try {
1038                    rewrite.rewriteAST(document, fSubType.getJavaProject().getOptions(true)).apply(document, TextEdit.UPDATE_REGIONS);
1039                } catch (MalformedTreeException exception) {
1040                    JavaPlugin.log(exception);
1041                } catch (BadLocationException exception) {
1042                    JavaPlugin.log(exception);
1043                }
1044                subUnit.getBuffer().setContents(document.get());
1045            } finally {
1046                RefactoringFileBuffers.release(fSubType.getCompilationUnit());
1047            }
1048            JavaModelUtil.reconcile(subUnit);
1049            final IJavaProject project= subUnit.getJavaProject();
1050            final ASTParser parser= ASTParser.newParser(AST.JLS3);
1051            parser.setWorkingCopyOwner(fOwner);
1052            parser.setResolveBindings(true);
1053            parser.setProject(project);
1054            parser.setCompilerOptions(RefactoringASTParser.getCompilerOptions(project));
1055            parser.createASTs(new ICompilationUnit[] { subUnit}, new String JavaDoc[0], new ASTRequestor() {
1056
1057                public final void acceptAST(final ICompilationUnit unit, final CompilationUnit node) {
1058                    try {
1059                        final IType subType= (IType) JavaModelUtil.findInCompilationUnit(unit, fSubType);
1060                        final AbstractTypeDeclaration subDeclaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(subType, node);
1061                        if (subDeclaration != null) {
1062                            final ITypeBinding subBinding= subDeclaration.resolveBinding();
1063                            if (subBinding != null) {
1064                                String JavaDoc name= null;
1065                                ITypeBinding superBinding= null;
1066                                final ITypeBinding[] superBindings= subBinding.getInterfaces();
1067                                for (int index= 0; index < superBindings.length; index++) {
1068                                    name= superBindings[index].getName();
1069                                    if (name.startsWith(fSuperName) && superBindings[index].getTypeArguments().length == subBinding.getTypeParameters().length)
1070                                        superBinding= superBindings[index];
1071                                }
1072                                if (superBinding != null) {
1073                                    solveSuperTypeConstraints(unit, node, subType, subBinding, superBinding, new SubProgressMonitor(monitor, 80), status);
1074                                    if (!status.hasFatalError()) {
1075                                        rewriteTypeOccurrences(manager, this, sourceRewrite, unit, node, replacements, status, new SubProgressMonitor(monitor, 200));
1076                                        if (manager.containsChangesIn(superUnit)) {
1077                                            final TextEditBasedChange change= manager.get(superUnit);
1078                                            if (change instanceof TextChange) {
1079                                                final TextEdit edit= ((TextChange) change).getEdit();
1080                                                if (edit != null) {
1081                                                    final IDocument document= new Document(superUnit.getBuffer().getContents());
1082                                                    try {
1083                                                        edit.apply(document, TextEdit.UPDATE_REGIONS);
1084                                                    } catch (MalformedTreeException exception) {
1085                                                        JavaPlugin.log(exception);
1086                                                        status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error));
1087                                                    } catch (BadLocationException exception) {
1088                                                        JavaPlugin.log(exception);
1089                                                        status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error));
1090                                                    }
1091                                                    fSuperSource= document.get();
1092                                                    manager.remove(superUnit);
1093                                                }
1094                                            }
1095                                        }
1096                                    }
1097                                }
1098                            }
1099                        }
1100                    } catch (JavaModelException exception) {
1101                        JavaPlugin.log(exception);
1102                        status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error));
1103                    }
1104                }
1105
1106                public final void acceptBinding(final String JavaDoc key, final IBinding binding) {
1107                    // Do nothing
1108
}
1109            }, new NullProgressMonitor());
1110        } finally {
1111            monitor.done();
1112        }
1113    }
1114
1115    /**
1116     * Determines whether extracted methods should be declared as abstract.
1117     *
1118     * @param declare
1119     * <code>true</code> to declare them public, <code>false</code>
1120     * otherwise
1121     */

1122    public final void setAbstract(final boolean declare) {
1123        fAbstract= declare;
1124    }
1125
1126    /**
1127     * Determines whether comments should be generated.
1128     *
1129     * @param comments
1130     * <code>true</code> to generate comments, <code>false</code>
1131     * otherwise
1132     */

1133    public final void setComments(final boolean comments) {
1134        fComments= comments;
1135    }
1136
1137    /**
1138     * Sets the members to be extracted.
1139     *
1140     * @param members
1141     * the members to be extracted
1142     * @throws JavaModelException
1143     * if an error occurs
1144     */

1145    public final void setExtractedMembers(final IMember[] members) throws JavaModelException {
1146        fMembers= members;
1147    }
1148
1149    /**
1150     * Determines whether extracted methods should be declared as public.
1151     *
1152     * @param declare
1153     * <code>true</code> to declare them public, <code>false</code>
1154     * otherwise
1155     */

1156    public final void setPublic(final boolean declare) {
1157        fPublic= declare;
1158    }
1159
1160    /**
1161     * Sets the new interface name.
1162     *
1163     * @param name
1164     * the new interface name
1165     */

1166    public final void setTypeName(final String JavaDoc name) {
1167        Assert.isNotNull(name);
1168        fSuperName= name;
1169    }
1170}
1171
Popular Tags