blob: 0db3a8c983cf2fdb2b8553147d270f7501398308 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.corext.refactoring.structure;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.text.edits.TextEditCopier;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.resources.IFile;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.GroupCategory;
import org.eclipse.ltk.core.refactoring.GroupCategorySet;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.TextChange;
import org.eclipse.ltk.core.refactoring.TextEditBasedChange;
import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTRequestor;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.TypeParameter;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2;
import org.eclipse.jdt.internal.corext.dom.Bindings;
import org.eclipse.jdt.internal.corext.refactoring.Checks;
import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptor;
import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorComment;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange;
import org.eclipse.jdt.internal.corext.refactoring.changes.CreateCompilationUnitChange;
import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
import org.eclipse.jdt.internal.corext.refactoring.changes.MultiStateCompilationUnitChange;
import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
import org.eclipse.jdt.internal.corext.refactoring.util.TextEditBasedChangeManager;
import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.JdtFlags;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.ui.CodeGeneration;
import org.eclipse.jdt.ui.JavaElementLabels;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
/**
* Refactoring processor for the extract supertype refactoring.
*
* @since 3.2
*/
public final class ExtractSupertypeProcessor extends PullUpRefactoringProcessor {
/** The extract attribute */
private static final String ATTRIBUTE_EXTRACT= "extract"; //$NON-NLS-1$
/** The types attribute */
private static final String ATTRIBUTE_TYPES= "types"; //$NON-NLS-1$
/** The id of the refactoring */
private static final String ID_EXTRACT_SUPERTYPE= "org.eclipse.jdt.ui.extract.superclass"; //$NON-NLS-1$
/** The extract supertype group category set */
private static final GroupCategorySet SET_EXTRACT_SUPERTYPE= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.extractSupertype", //$NON-NLS-1$
RefactoringCoreMessages.ExtractSupertypeProcessor_category_name, RefactoringCoreMessages.ExtractSupertypeProcessor_category_description));
/**
* The changes of the working copy layer (element type:
* <ICompilationUnit, TextEditBasedChange>)
* <p>
* The compilation units are all primary working copies or normal
* compilation units.
* </p>
*/
private final Map fLayerChanges= new HashMap();
/** The possible extract supertype candidates, or the empty array */
private IType[] fPossibleCandidates= {};
/** The source of the supertype */
private String fSuperSource;
/** The name of the extracted type */
private String fTypeName= ""; //$NON-NLS-1$
/** The types where to extract the supertype */
private IType[] fTypesToExtract= {};
/**
* Creates a new extract supertype refactoring processor.
*
* @param members
* the members to extract, or <code>null</code> if invoked by
* scripting
* @param settings
* the code generation settings, or <code>null</code> if
* invoked by scripting
*/
public ExtractSupertypeProcessor(final IMember[] members, final CodeGenerationSettings settings) {
super(members, settings, true);
if (members != null) {
final IType declaring= getDeclaringType();
if (declaring != null)
fTypesToExtract= new IType[] { declaring};
}
}
/**
* {@inheritDoc}
*/
protected final RefactoringStatus checkDeclaringSuperTypes(final IProgressMonitor monitor) throws JavaModelException {
return new RefactoringStatus();
}
protected CompilationUnitRewrite getCompilationUnitRewrite(final Map rewrites, final ICompilationUnit unit) {
Assert.isNotNull(rewrites);
Assert.isNotNull(unit);
CompilationUnitRewrite rewrite= (CompilationUnitRewrite) rewrites.get(unit);
if (rewrite == null) {
rewrite= new CompilationUnitRewrite(fOwner, unit);
rewrite.rememberContent();
rewrites.put(unit, rewrite);
}
return rewrite;
}
/**
* Checks whether the compilation unit to be extracted is valid.
*
* @return a status describing the outcome of the
*/
public RefactoringStatus checkExtractedCompilationUnit() {
final RefactoringStatus status= new RefactoringStatus();
final ICompilationUnit cu= getDeclaringType().getCompilationUnit();
if (fTypeName == null || "".equals(fTypeName)) //$NON-NLS-1$
return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.Checks_Choose_name);
status.merge(Checks.checkTypeName(fTypeName));
if (status.hasFatalError())
return status;
status.merge(Checks.checkCompilationUnitName(JavaModelUtil.getRenamedCUName(cu, fTypeName)));
if (status.hasFatalError())
return status;
status.merge(Checks.checkCompilationUnitNewName(cu, fTypeName));
return status;
}
/**
* {@inheritDoc}
*/
public RefactoringStatus checkFinalConditions(final IProgressMonitor monitor, final CheckConditionsContext context) throws CoreException, OperationCanceledException {
final RefactoringStatus status= new RefactoringStatus();
try {
monitor.beginTask("", 1); //$NON-NLS-1$
monitor.setTaskName(RefactoringCoreMessages.ExtractSupertypeProcessor_checking);
status.merge(checkExtractedCompilationUnit());
if (status.hasFatalError())
return status;
return super.checkFinalConditions(new SubProgressMonitor(monitor, 1), context);
} finally {
monitor.done();
}
}
/**
* Computes the destination type based on the new name.
*
* @return the destination type
*/
public IType computeExtractedType(final String name) {
if (name != null && !name.equals("")) {//$NON-NLS-1$
final IType declaring= getDeclaringType();
try {
final ICompilationUnit[] units= declaring.getPackageFragment().getCompilationUnits(fOwner);
final String newName= JavaModelUtil.getRenamedCUName(declaring.getCompilationUnit(), name);
ICompilationUnit result= null;
for (int index= 0; index < units.length; index++) {
if (units[index].getElementName().equals(newName))
result= units[index];
}
if (result != null) {
final IType type= result.getType(name);
setDestinationType(type);
return type;
}
} catch (JavaModelException exception) {
JavaPlugin.log(exception);
}
}
return null;
}
/**
* {@inheritDoc}
*/
public Change createChange(final IProgressMonitor monitor) throws CoreException, OperationCanceledException {
try {
final Map arguments= new HashMap();
String project= null;
final IType declaring= getDeclaringType();
final IJavaProject javaProject= declaring.getJavaProject();
if (javaProject != null)
project= javaProject.getElementName();
int flags= JavaRefactoringDescriptor.JAR_IMPORTABLE | JavaRefactoringDescriptor.JAR_REFACTORABLE | RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE;
try {
if (declaring.isLocal() || declaring.isAnonymous())
flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
} catch (JavaModelException exception) {
JavaPlugin.log(exception);
}
final String description= Messages.format(RefactoringCoreMessages.ExtractSupertypeProcessor_descriptor_description_short, fTypeName);
final String header= Messages.format(RefactoringCoreMessages.ExtractSupertypeProcessor_descriptor_description, new String[] { JavaElementLabels.getElementLabel(fDestinationType, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(fCachedDeclaringType, JavaElementLabels.ALL_FULLY_QUALIFIED)});
final JavaRefactoringDescriptorComment comment= new JavaRefactoringDescriptorComment(this, header);
final IType[] types= getTypesToExtract();
String[] settings= new String[types.length];
for (int index= 0; index < settings.length; index++)
settings[index]= JavaElementLabels.getElementLabel(types[index], JavaElementLabels.ALL_FULLY_QUALIFIED);
comment.addSetting(JavaRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ExtractSupertypeProcessor_subtypes_pattern, settings));
comment.addSetting(Messages.format(RefactoringCoreMessages.ExtractSupertypeProcessor_refactored_element_pattern, JavaElementLabels.getElementLabel(fDestinationType, JavaElementLabels.ALL_FULLY_QUALIFIED)));
settings= new String[fMembersToMove.length];
for (int index= 0; index < settings.length; index++)
settings[index]= JavaElementLabels.getElementLabel(fMembersToMove[index], JavaElementLabels.ALL_FULLY_QUALIFIED);
comment.addSetting(JavaRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ExtractInterfaceProcessor_extracted_members_pattern, settings));
addSuperTypeSettings(comment, true);
final JavaRefactoringDescriptor descriptor= new JavaRefactoringDescriptor(ID_EXTRACT_SUPERTYPE, project, description, comment.asString(), arguments, flags);
arguments.put(JavaRefactoringDescriptor.ATTRIBUTE_NAME, fTypeName);
arguments.put(JavaRefactoringDescriptor.ATTRIBUTE_INPUT, descriptor.elementToHandle(getDeclaringType()));
arguments.put(ATTRIBUTE_REPLACE, Boolean.valueOf(fReplace).toString());
arguments.put(ATTRIBUTE_INSTANCEOF, Boolean.valueOf(fInstanceOf).toString());
arguments.put(ATTRIBUTE_STUBS, Boolean.valueOf(fCreateMethodStubs).toString());
arguments.put(ATTRIBUTE_EXTRACT, new Integer(fMembersToMove.length).toString());
for (int offset= 0; offset < fMembersToMove.length; offset++)
arguments.put(JavaRefactoringDescriptor.ATTRIBUTE_ELEMENT + (offset + 1), descriptor.elementToHandle(fMembersToMove[offset]));
arguments.put(ATTRIBUTE_DELETE, new Integer(fDeletedMethods.length).toString());
for (int offset= 0; offset < fDeletedMethods.length; offset++)
arguments.put(JavaRefactoringDescriptor.ATTRIBUTE_ELEMENT + (offset + fMembersToMove.length + 1), descriptor.elementToHandle(fDeletedMethods[offset]));
arguments.put(ATTRIBUTE_ABSTRACT, new Integer(fAbstractMethods.length).toString());
for (int offset= 0; offset < fAbstractMethods.length; offset++)
arguments.put(JavaRefactoringDescriptor.ATTRIBUTE_ELEMENT + (offset + fMembersToMove.length + fDeletedMethods.length + 1), descriptor.elementToHandle(fAbstractMethods[offset]));
arguments.put(ATTRIBUTE_TYPES, new Integer(fTypesToExtract.length).toString());
for (int offset= 0; offset < fTypesToExtract.length; offset++)
arguments.put(JavaRefactoringDescriptor.ATTRIBUTE_ELEMENT + (offset + fMembersToMove.length + fDeletedMethods.length + fAbstractMethods.length + 1), descriptor.elementToHandle(fTypesToExtract[offset]));
final DynamicValidationRefactoringChange change= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.ExtractSupertypeProcessor_extract_supertype, fChangeManager.getAllChanges());
final IFile file= ResourceUtil.getFile(declaring.getCompilationUnit());
if (fSuperSource != null && fSuperSource.length() > 0)
change.add(new CreateCompilationUnitChange(declaring.getPackageFragment().getCompilationUnit(JavaModelUtil.getRenamedCUName(declaring.getCompilationUnit(), fTypeName)), fSuperSource, file.getCharset(false)));
return change;
} finally {
monitor.done();
clearCaches();
}
}
/**
* Creates the new extracted supertype.
*
* @param superType
* the super type, or <code>null</code> if no super type (ie.
* <code>java.lang.Object</code>) is available
* @param monitor
* the progress monitor
* @return a status describing the outcome of the operation
* @throws CoreException
* if an error occurs
*/
protected final RefactoringStatus createExtractedSuperType(final IType superType, final IProgressMonitor monitor) throws CoreException {
Assert.isNotNull(monitor);
fSuperSource= null;
final RefactoringStatus status= new RefactoringStatus();
try {
monitor.beginTask(RefactoringCoreMessages.ExtractSupertypeProcessor_preparing, 20);
final IType declaring= getDeclaringType();
final CompilationUnitRewrite declaringRewrite= new CompilationUnitRewrite(fOwner, declaring.getCompilationUnit());
final AbstractTypeDeclaration declaringDeclaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(declaring, declaringRewrite.getRoot());
if (declaringDeclaration != null) {
final String name= JavaModelUtil.getRenamedCUName(declaring.getCompilationUnit(), fTypeName);
final ICompilationUnit original= declaring.getPackageFragment().getCompilationUnit(name);
final ICompilationUnit copy= getSharedWorkingCopy(original.getPrimary(), new SubProgressMonitor(monitor, 10));
fSuperSource= createSuperTypeSource(copy, superType, declaringDeclaration, status, new SubProgressMonitor(monitor, 10));
if (fSuperSource != null) {
copy.getBuffer().setContents(fSuperSource);
JavaModelUtil.reconcile(copy);
}
}
} finally {
monitor.done();
}
return status;
}
/**
* Creates a working copy for the modified subtype.
*
* @param unit
* the compilation unit
* @param root
* the compilation unit node
* @param subDeclaration
* the declaration of the subtype to modify
* @param extractedType
* the extracted super type
* @param extractedBinding
* the binding of the extracted super type
* @param status
* the refactoring status
*/
protected final void createModifiedSubType(final ICompilationUnit unit, final CompilationUnit root, final IType extractedType, final ITypeBinding extractedBinding, final AbstractTypeDeclaration subDeclaration, final RefactoringStatus status) {
Assert.isNotNull(unit);
Assert.isNotNull(subDeclaration);
Assert.isNotNull(extractedType);
try {
final CompilationUnitRewrite rewrite= new CompilationUnitRewrite(fOwner, unit, root);
createTypeSignature(rewrite, subDeclaration, extractedType, extractedBinding, new NullProgressMonitor());
final Document document= new Document(unit.getBuffer().getContents());
final CompilationUnitChange change= rewrite.createChange();
if (change != null) {
fLayerChanges.put(unit.getPrimary(), change);
final TextEdit edit= change.getEdit();
if (edit != null) {
final TextEditCopier copier= new TextEditCopier(edit);
final TextEdit copy= copier.perform();
copy.apply(document, TextEdit.NONE);
}
}
final ICompilationUnit copy= getSharedWorkingCopy(unit, new NullProgressMonitor());
copy.getBuffer().setContents(document.get());
JavaModelUtil.reconcile(copy);
} catch (CoreException exception) {
JavaPlugin.log(exception);
status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractSupertypeProcessor_unexpected_exception_on_layer));
} catch (MalformedTreeException exception) {
JavaPlugin.log(exception);
status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractSupertypeProcessor_unexpected_exception_on_layer));
} catch (BadLocationException exception) {
JavaPlugin.log(exception);
status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractSupertypeProcessor_unexpected_exception_on_layer));
}
}
/**
* Creates the necessary constructors for the extracted supertype.
*
* @param targetRewrite
* the target compilation unit rewrite
* @param superType
* the super type, or <code>null</code> if no super type (ie.
* <code>java.lang.Object</code>) is available
* @param targetDeclaration
* the type declaration of the target type
* @param status
* the refactoring status
*/
protected final void createNecessaryConstructors(final CompilationUnitRewrite targetRewrite, final IType superType, final AbstractTypeDeclaration targetDeclaration, final RefactoringStatus status) {
Assert.isNotNull(targetRewrite);
Assert.isNotNull(targetDeclaration);
if (superType != null) {
final ITypeBinding binding= targetDeclaration.resolveBinding();
if (binding != null && binding.isClass()) {
final IMethodBinding[] bindings= StubUtility2.getVisibleConstructors(binding, true, true);
int deprecationCount= 0;
for (int i= 0; i < bindings.length; i++) {
if (bindings[i].isDeprecated())
deprecationCount++;
}
final ListRewrite rewrite= targetRewrite.getASTRewrite().getListRewrite(targetDeclaration, TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
if (rewrite != null) {
boolean createDeprecated= deprecationCount == bindings.length;
for (int i= 0; i < bindings.length; i++) {
IMethodBinding curr= bindings[i];
if (!curr.isDeprecated() || createDeprecated) {
MethodDeclaration stub;
try {
stub= StubUtility2.createConstructorStub(targetRewrite.getCu(), targetRewrite.getASTRewrite(), targetRewrite.getImportRewrite(), curr, binding.getName(), Modifier.PUBLIC, false, false, fSettings);
if (stub != null)
rewrite.insertLast(stub, null);
} catch (CoreException exception) {
JavaPlugin.log(exception);
status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractSupertypeProcessor_unexpected_exception_on_layer));
}
}
}
}
}
}
}
/**
* Creates the source for the new compilation unit containing the supertype.
*
* @param extractedWorkingCopy
* the working copy of the new extracted supertype
* @param superType
* the super type, or <code>null</code> if no super type (ie.
* <code>java.lang.Object</code>) is available
* @param declaringDeclaration
* the declaration of the declaring type
* @param status
* the refactoring status
* @param monitor
* the progress monitor to display progress
* @return the source of the new compilation unit, or <code>null</code>
* @throws CoreException
* if an error occurs
*/
protected final String createSuperTypeSource(final ICompilationUnit extractedWorkingCopy, final IType superType, final AbstractTypeDeclaration declaringDeclaration, final RefactoringStatus status, final IProgressMonitor monitor) throws CoreException {
Assert.isNotNull(extractedWorkingCopy);
Assert.isNotNull(declaringDeclaration);
Assert.isNotNull(status);
Assert.isNotNull(monitor);
String source= null;
try {
monitor.beginTask("", 2); //$NON-NLS-1$
monitor.setTaskName(RefactoringCoreMessages.ExtractSupertypeProcessor_preparing);
final IType declaring= getDeclaringType();
final String delimiter= StubUtility.getLineDelimiterUsed(extractedWorkingCopy.getJavaProject());
String typeComment= null;
String fileComment= null;
if (fSettings.createComments) {
final ITypeParameter[] parameters= declaring.getTypeParameters();
final String[] names= new String[parameters.length];
for (int index= 0; index < parameters.length; index++)
names[index]= parameters[index].getElementName();
typeComment= CodeGeneration.getTypeComment(extractedWorkingCopy, fTypeName, names, delimiter);
fileComment= CodeGeneration.getFileComment(extractedWorkingCopy, delimiter);
}
final StringBuffer buffer= new StringBuffer(64);
createTypeDeclaration(extractedWorkingCopy, superType, declaringDeclaration, typeComment, buffer, status, new SubProgressMonitor(monitor, 1));
final String imports= createTypeImports(extractedWorkingCopy, monitor);
source= createTypeTemplate(extractedWorkingCopy, imports, fileComment, "", buffer.toString()); //$NON-NLS-1$
if (source == null) {
if (!declaring.getPackageFragment().isDefaultPackage()) {
if (imports.length() > 0)
buffer.insert(0, imports);
buffer.insert(0, "package " + declaring.getPackageFragment().getElementName() + ";"); //$NON-NLS-1$//$NON-NLS-2$
}
source= buffer.toString();
}
final IDocument document= new Document(source);
final TextEdit edit= CodeFormatterUtil.format2(CodeFormatter.K_COMPILATION_UNIT, source, 0, delimiter, extractedWorkingCopy.getJavaProject().getOptions(true));
if (edit != null) {
try {
edit.apply(document, TextEdit.UPDATE_REGIONS);
} catch (MalformedTreeException exception) {
JavaPlugin.log(exception);
status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractSupertypeProcessor_unexpected_exception_on_layer));
} catch (BadLocationException exception) {
JavaPlugin.log(exception);
status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractSupertypeProcessor_unexpected_exception_on_layer));
}
source= document.get();
}
} finally {
monitor.done();
}
return source;
}
/**
* Creates the declaration of the new supertype, excluding any comments or
* package declaration.
*
* @param extractedWorkingCopy
* the working copy of the new extracted supertype
* @param superType
* the super type, or <code>null</code> if no super type (ie.
* <code>java.lang.Object</code>) is available
* @param declaringDeclaration
* the declaration of the declaring type
* @param comment
* the comment of the new type declaration
* @param buffer
* the string buffer containing the declaration
* @param status
* the refactoring status
* @param monitor
* the progress monitor to use
* @throws CoreException
* if an error occurs
*/
protected final void createTypeDeclaration(final ICompilationUnit extractedWorkingCopy, final IType superType, final AbstractTypeDeclaration declaringDeclaration, final String comment, final StringBuffer buffer, final RefactoringStatus status, final IProgressMonitor monitor) throws CoreException {
Assert.isNotNull(extractedWorkingCopy);
Assert.isNotNull(declaringDeclaration);
Assert.isNotNull(buffer);
Assert.isNotNull(status);
Assert.isNotNull(monitor);
try {
monitor.beginTask("", 1); //$NON-NLS-1$
monitor.setTaskName(RefactoringCoreMessages.ExtractSupertypeProcessor_preparing);
final IJavaProject project= extractedWorkingCopy.getJavaProject();
final String delimiter= StubUtility.getLineDelimiterUsed(project);
if (comment != null && !"".equals(comment)) { //$NON-NLS-1$
buffer.append(comment);
buffer.append(delimiter);
}
buffer.append(JdtFlags.VISIBILITY_STRING_PUBLIC);
if (superType != null && Flags.isAbstract(superType.getFlags())) {
buffer.append(' ');
buffer.append("abstract "); //$NON-NLS-1$
}
buffer.append(' ');
buffer.append("class "); //$NON-NLS-1$
buffer.append(fTypeName);
if (superType != null && !"java.lang.Object".equals(superType.getFullyQualifiedName())) { //$NON-NLS-1$
buffer.append(' ');
if (superType.isInterface())
buffer.append("implements "); //$NON-NLS-1$
else
buffer.append("extends "); //$NON-NLS-1$
buffer.append(superType.getElementName());
}
buffer.append(" {"); //$NON-NLS-1$
buffer.append(delimiter);
buffer.append(delimiter);
buffer.append('}');
final String string= buffer.toString();
extractedWorkingCopy.getBuffer().setContents(string);
final IDocument document= new Document(string);
final CompilationUnitRewrite targetRewrite= new CompilationUnitRewrite(fOwner, extractedWorkingCopy);
final AbstractTypeDeclaration targetDeclaration= (AbstractTypeDeclaration) targetRewrite.getRoot().types().get(0);
createTypeParameters(targetRewrite, superType, declaringDeclaration, targetDeclaration);
createTypeSignature(targetRewrite, superType, declaringDeclaration, targetDeclaration);
createNecessaryConstructors(targetRewrite, superType, targetDeclaration, status);
final TextEdit edit= targetRewrite.createChange().getEdit();
try {
edit.apply(document, TextEdit.UPDATE_REGIONS);
} catch (MalformedTreeException exception) {
JavaPlugin.log(exception);
status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractSupertypeProcessor_unexpected_exception_on_layer));
} catch (BadLocationException exception) {
JavaPlugin.log(exception);
status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractSupertypeProcessor_unexpected_exception_on_layer));
}
buffer.setLength(0);
buffer.append(document.get());
} finally {
monitor.done();
}
}
/**
* Creates the type parameters of the new supertype.
*
* @param targetRewrite
* the target compilation unit rewrite
* @param subType
* the subtype
* @param sourceDeclaration
* the type declaration of the source type
* @param targetDeclaration
* the type declaration of the target type
*/
protected final void createTypeParameters(final CompilationUnitRewrite targetRewrite, final IType subType, final AbstractTypeDeclaration sourceDeclaration, final AbstractTypeDeclaration targetDeclaration) {
Assert.isNotNull(targetRewrite);
Assert.isNotNull(sourceDeclaration);
Assert.isNotNull(targetDeclaration);
if (sourceDeclaration instanceof TypeDeclaration) {
TypeParameter parameter= null;
final ListRewrite rewrite= targetRewrite.getASTRewrite().getListRewrite(targetDeclaration, TypeDeclaration.TYPE_PARAMETERS_PROPERTY);
for (final Iterator iterator= ((TypeDeclaration) sourceDeclaration).typeParameters().iterator(); iterator.hasNext();) {
parameter= (TypeParameter) iterator.next();
final ASTNode node= ASTNode.copySubtree(targetRewrite.getAST(), parameter);
rewrite.insertLast(node, null);
}
}
}
/**
* Creates a new type signature of a subtype.
*
* @param subRewrite
* the compilation unit rewrite of a subtype
* @param declaration
* the type declaration of a subtype
* @param extractedType
* the extracted super type
* @param extractedBinding
* the binding of the extracted super type
* @param monitor
* the progress monitor to use
* @throws JavaModelException
* if the type parameters cannot be retrieved
*/
protected final void createTypeSignature(final CompilationUnitRewrite subRewrite, final AbstractTypeDeclaration declaration, final IType extractedType, final ITypeBinding extractedBinding, final IProgressMonitor monitor) throws JavaModelException {
Assert.isNotNull(subRewrite);
Assert.isNotNull(declaration);
Assert.isNotNull(extractedType);
Assert.isNotNull(monitor);
try {
monitor.beginTask(RefactoringCoreMessages.ExtractSupertypeProcessor_preparing, 10);
final AST ast= subRewrite.getAST();
Type type= null;
if (extractedBinding != null) {
type= subRewrite.getImportRewrite().addImport(extractedBinding, ast);
} else {
subRewrite.getImportRewrite().addImport(extractedType.getFullyQualifiedName('.'));
type= ast.newSimpleType(ast.newSimpleName(extractedType.getElementName()));
}
subRewrite.getImportRemover().registerAddedImport(extractedType.getFullyQualifiedName('.'));
if (type != null) {
final ITypeParameter[] parameters= extractedType.getTypeParameters();
if (parameters.length > 0) {
final ParameterizedType parameterized= ast.newParameterizedType(type);
for (int index= 0; index < parameters.length; index++)
parameterized.typeArguments().add(ast.newSimpleType(ast.newSimpleName(parameters[index].getElementName())));
type= parameterized;
}
}
final ASTRewrite rewriter= subRewrite.getASTRewrite();
if (type != null && declaration instanceof TypeDeclaration) {
final TypeDeclaration extended= (TypeDeclaration) declaration;
final Type superClass= extended.getSuperclassType();
if (superClass != null)
rewriter.replace(superClass, type, subRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractSupertypeProcessor_add_supertype, SET_EXTRACT_SUPERTYPE));
else
rewriter.set(extended, TypeDeclaration.SUPERCLASS_TYPE_PROPERTY, type, subRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractSupertypeProcessor_add_supertype, SET_EXTRACT_SUPERTYPE));
}
} finally {
monitor.done();
}
}
/**
* Creates the type signature of the extracted supertype.
*
* @param targetRewrite
* the target compilation unit rewrite
* @param superType
* the super type, or <code>null</code> if no super type (ie.
* <code>java.lang.Object</code>) is available
* @param declaringDeclaration
* the declaration of the declaring type
* @param targetDeclaration
* the type declaration of the target type
*/
protected final void createTypeSignature(final CompilationUnitRewrite targetRewrite, final IType superType, final AbstractTypeDeclaration declaringDeclaration, final AbstractTypeDeclaration targetDeclaration) {
Assert.isNotNull(targetRewrite);
Assert.isNotNull(declaringDeclaration);
Assert.isNotNull(targetDeclaration);
if (declaringDeclaration instanceof TypeDeclaration) {
final TypeDeclaration declaration= (TypeDeclaration) declaringDeclaration;
final Type superclassType= declaration.getSuperclassType();
if (superclassType != null) {
Type type= null;
final ITypeBinding binding= superclassType.resolveBinding();
if (binding != null) {
type= targetRewrite.getImportRewrite().addImport(binding, targetRewrite.getAST());
targetRewrite.getImportRemover().registerAddedImports(type);
}
if (type != null && targetDeclaration instanceof TypeDeclaration) {
final TypeDeclaration extended= (TypeDeclaration) targetDeclaration;
final Type targetSuperType= extended.getSuperclassType();
if (targetSuperType != null) {
targetRewrite.getASTRewrite().replace(targetSuperType, type, null);
} else {
targetRewrite.getASTRewrite().set(extended, TypeDeclaration.SUPERCLASS_TYPE_PROPERTY, type, null);
}
}
}
}
}
/**
* {@inheritDoc}
*/
public final RefactoringStatus createWorkingCopyLayer(final IProgressMonitor monitor) {
Assert.isNotNull(monitor);
final RefactoringStatus status= new RefactoringStatus();
try {
monitor.beginTask(RefactoringCoreMessages.ExtractSupertypeProcessor_preparing, 70);
status.merge(super.createWorkingCopyLayer(new SubProgressMonitor(monitor, 10)));
final IType declaring= getDeclaringType();
status.merge(createExtractedSuperType(getDeclaringSuperTypeHierarchy(new SubProgressMonitor(monitor, 10)).getSuperclass(declaring), new SubProgressMonitor(monitor, 10)));
if (status.hasFatalError())
return status;
final IType extractedType= computeExtractedType(fTypeName);
setDestinationType(extractedType);
final List subTypes= new ArrayList(Arrays.asList(fTypesToExtract));
if (!subTypes.contains(declaring))
subTypes.add(declaring);
final Map unitToTypes= new HashMap(subTypes.size());
final Set units= new HashSet(subTypes.size());
for (int index= 0; index < subTypes.size(); index++) {
final IType type= (IType) subTypes.get(index);
final ICompilationUnit unit= type.getCompilationUnit();
units.add(unit);
Collection collection= (Collection) unitToTypes.get(unit);
if (collection == null) {
collection= new ArrayList(2);
unitToTypes.put(unit, collection);
}
collection.add(type);
}
final Map projectToUnits= new HashMap();
Collection collection= null;
IJavaProject project= null;
ICompilationUnit current= null;
for (final Iterator iterator= units.iterator(); iterator.hasNext();) {
current= (ICompilationUnit) iterator.next();
project= current.getJavaProject();
collection= (Collection) projectToUnits.get(project);
if (collection == null) {
collection= new ArrayList();
projectToUnits.put(project, collection);
}
collection.add(current);
}
final ITypeBinding[] extractBindings= { null};
final ASTParser extractParser= ASTParser.newParser(AST.JLS3);
extractParser.setWorkingCopyOwner(fOwner);
extractParser.setResolveBindings(true);
extractParser.setProject(project);
extractParser.setSource(extractedType.getCompilationUnit());
final CompilationUnit extractUnit= (CompilationUnit) extractParser.createAST(new SubProgressMonitor(monitor, 10));
if (extractUnit != null) {
final AbstractTypeDeclaration extractDeclaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(extractedType, extractUnit);
if (extractDeclaration != null)
extractBindings[0]= extractDeclaration.resolveBinding();
}
final ASTParser parser= ASTParser.newParser(AST.JLS3);
final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 30);
try {
final Set keySet= projectToUnits.keySet();
subMonitor.beginTask("", keySet.size()); //$NON-NLS-1$
subMonitor.setTaskName(RefactoringCoreMessages.ExtractSupertypeProcessor_preparing);
for (final Iterator iterator= keySet.iterator(); iterator.hasNext();) {
project= (IJavaProject) iterator.next();
collection= (Collection) projectToUnits.get(project);
parser.setWorkingCopyOwner(fOwner);
parser.setResolveBindings(true);
parser.setProject(project);
parser.setCompilerOptions(RefactoringASTParser.getCompilerOptions(project));
final IProgressMonitor subsubMonitor= new SubProgressMonitor(subMonitor, 1);
try {
subsubMonitor.beginTask("", collection.size()); //$NON-NLS-1$
subsubMonitor.setTaskName(RefactoringCoreMessages.ExtractSupertypeProcessor_preparing);
parser.createASTs((ICompilationUnit[]) collection.toArray(new ICompilationUnit[collection.size()]), new String[0], new ASTRequestor() {
public final void acceptAST(final ICompilationUnit unit, final CompilationUnit node) {
try {
final Collection types= (Collection) unitToTypes.get(unit);
if (types != null) {
for (final Iterator innerIterator= types.iterator(); innerIterator.hasNext();) {
final IType currentType= (IType) innerIterator.next();
final AbstractTypeDeclaration currentDeclaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(currentType, node);
if (currentDeclaration != null)
createModifiedSubType(unit, node, extractedType, extractBindings[0], currentDeclaration, status);
}
}
} catch (CoreException exception) {
JavaPlugin.log(exception);
status.merge(RefactoringStatus.createFatalErrorStatus(exception.getLocalizedMessage()));
} finally {
subsubMonitor.worked(1);
}
}
public final void acceptBinding(final String key, final IBinding binding) {
// Do nothing
}
}, subsubMonitor);
} finally {
subsubMonitor.done();
}
}
} finally {
subMonitor.done();
}
} catch (CoreException exception) {
JavaPlugin.log(exception);
status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractSupertypeProcessor_unexpected_exception_on_layer));
} finally {
monitor.done();
}
return status;
}
/**
* {@inheritDoc}
*/
public IType[] getCandidateTypes(final RefactoringStatus status, final IProgressMonitor monitor) {
Assert.isNotNull(monitor);
if (fPossibleCandidates == null || fPossibleCandidates.length == 0) {
final IType declaring= getDeclaringType();
if (declaring != null) {
try {
monitor.beginTask(RefactoringCoreMessages.ExtractSupertypeProcessor_computing_possible_types, 10);
final IType superType= getDeclaringSuperTypeHierarchy(new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)).getSuperclass(declaring);
if (superType != null) {
fPossibleCandidates= superType.newTypeHierarchy(fOwner, new SubProgressMonitor(monitor, 9, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)).getSubtypes(superType);
final LinkedList list= new LinkedList(Arrays.asList(fPossibleCandidates));
final Set names= new HashSet();
for (final Iterator iterator= list.iterator(); iterator.hasNext();) {
final IType type= (IType) iterator.next();
if (type.isReadOnly() || type.isBinary() || type.isAnonymous() || !type.isClass() || names.contains(type.getFullyQualifiedName()))
iterator.remove();
else
names.add(type.getFullyQualifiedName());
}
fPossibleCandidates= (IType[]) list.toArray(new IType[list.size()]);
}
} catch (JavaModelException exception) {
JavaPlugin.log(exception);
} finally {
monitor.done();
}
}
}
return fPossibleCandidates;
}
/**
* {@inheritDoc}
*/
public Object[] getElements() {
return new Object[] { getDeclaringType()};
}
/**
* Returns the extracted type.
*
* @return the extracted type, or <code>null</code>
*/
public IType getExtractedType() {
return getDestinationType();
}
/**
* Returns the type name.
*
* @return the type name
*/
public String getTypeName() {
return fTypeName;
}
/**
* Returns the types to extract. The declaring type may or may not be
* contained in the result.
*
* @return the types to extract
*/
public IType[] getTypesToExtract() {
return fTypesToExtract;
}
/**
* {@inheritDoc}
*/
public RefactoringStatus initialize(final RefactoringArguments arguments) {
if (arguments instanceof JavaRefactoringArguments) {
final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments;
final String name= extended.getAttribute(JavaRefactoringDescriptor.ATTRIBUTE_NAME);
if (name != null && !"".equals(name)) //$NON-NLS-1$
fTypeName= name;
else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptor.ATTRIBUTE_NAME));
String handle= extended.getAttribute(JavaRefactoringDescriptor.ATTRIBUTE_INPUT);
if (handle != null) {
final IJavaElement element= JavaRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
if (element == null || element.getElementType() != IJavaElement.TYPE)
return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), ID_EXTRACT_SUPERTYPE);
IType type= null;
final ICompilationUnit unit= ((IType) element).getCompilationUnit();
if (unit != null && unit.exists()) {
try {
final ICompilationUnit copy= getSharedWorkingCopy(unit, new NullProgressMonitor());
final IJavaElement[] elements= copy.findElements(element);
if (elements != null && elements.length == 1 && elements[0] instanceof IType && elements[0].exists())
type= (IType) elements[0];
} catch (JavaModelException exception) {
// TODO: log exception
}
}
if (type != null)
fCachedDeclaringType= type;
else
return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), ID_EXTRACT_SUPERTYPE);
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptor.ATTRIBUTE_INPUT));
final String stubs= extended.getAttribute(ATTRIBUTE_STUBS);
if (stubs != null) {
fCreateMethodStubs= Boolean.valueOf(stubs).booleanValue();
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_STUBS));
final String instance= extended.getAttribute(ATTRIBUTE_INSTANCEOF);
if (instance != null) {
fInstanceOf= Boolean.valueOf(instance).booleanValue();
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_INSTANCEOF));
final String replace= extended.getAttribute(ATTRIBUTE_REPLACE);
if (replace != null) {
fReplace= Boolean.valueOf(replace).booleanValue();
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_REPLACE));
int extractCount= 0;
int abstractCount= 0;
int deleteCount= 0;
int typeCount= 0;
String value= extended.getAttribute(ATTRIBUTE_ABSTRACT);
if (value != null && !"".equals(value)) {//$NON-NLS-1$
try {
abstractCount= Integer.parseInt(value);
} catch (NumberFormatException exception) {
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_ABSTRACT));
}
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_ABSTRACT));
value= extended.getAttribute(ATTRIBUTE_DELETE);
if (value != null && !"".equals(value)) {//$NON-NLS-1$
try {
deleteCount= Integer.parseInt(value);
} catch (NumberFormatException exception) {
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DELETE));
}
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DELETE));
value= extended.getAttribute(ATTRIBUTE_EXTRACT);
if (value != null && !"".equals(value)) {//$NON-NLS-1$
try {
extractCount= Integer.parseInt(value);
} catch (NumberFormatException exception) {
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_EXTRACT));
}
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_EXTRACT));
value= extended.getAttribute(ATTRIBUTE_TYPES);
if (value != null && !"".equals(value)) {//$NON-NLS-1$
try {
typeCount= Integer.parseInt(value);
} catch (NumberFormatException exception) {
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_TYPES));
}
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_TYPES));
final RefactoringStatus status= new RefactoringStatus();
List elements= new ArrayList();
for (int index= 0; index < extractCount; index++) {
final String attribute= JavaRefactoringDescriptor.ATTRIBUTE_ELEMENT + (index + 1);
handle= extended.getAttribute(attribute);
if (handle != null && !"".equals(handle)) { //$NON-NLS-1$
final IJavaElement element= JavaRefactoringDescriptor.handleToElement(fOwner, extended.getProject(), handle, false);
if (element == null || !element.exists())
status.merge(ScriptableRefactoring.createInputWarningStatus(element, getRefactoring().getName(), ID_EXTRACT_SUPERTYPE));
else
elements.add(element);
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, attribute));
}
fMembersToMove= (IMember[]) elements.toArray(new IMember[elements.size()]);
elements= new ArrayList();
for (int index= 0; index < deleteCount; index++) {
final String attribute= JavaRefactoringDescriptor.ATTRIBUTE_ELEMENT + (extractCount + index + 1);
handle= extended.getAttribute(attribute);
if (handle != null && !"".equals(handle)) { //$NON-NLS-1$
final IJavaElement element= JavaRefactoringDescriptor.handleToElement(fOwner, extended.getProject(), handle, false);
if (element == null || !element.exists())
status.merge(ScriptableRefactoring.createInputWarningStatus(element, getRefactoring().getName(), ID_EXTRACT_SUPERTYPE));
else
elements.add(element);
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, attribute));
}
fDeletedMethods= (IMethod[]) elements.toArray(new IMethod[elements.size()]);
elements= new ArrayList();
for (int index= 0; index < abstractCount; index++) {
final String attribute= JavaRefactoringDescriptor.ATTRIBUTE_ELEMENT + (extractCount + abstractCount + index + 1);
handle= extended.getAttribute(attribute);
if (handle != null && !"".equals(handle)) { //$NON-NLS-1$
final IJavaElement element= JavaRefactoringDescriptor.handleToElement(fOwner, extended.getProject(), handle, false);
if (element == null || !element.exists())
status.merge(ScriptableRefactoring.createInputWarningStatus(element, getRefactoring().getName(), ID_EXTRACT_SUPERTYPE));
else
elements.add(element);
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, attribute));
}
fAbstractMethods= (IMethod[]) elements.toArray(new IMethod[elements.size()]);
elements= new ArrayList();
for (int index= 0; index < typeCount; index++) {
final String attribute= JavaRefactoringDescriptor.ATTRIBUTE_ELEMENT + (extractCount + abstractCount + deleteCount + index + 1);
handle= extended.getAttribute(attribute);
if (handle != null && !"".equals(handle)) { //$NON-NLS-1$
final IJavaElement element= JavaRefactoringDescriptor.handleToElement(fOwner, extended.getProject(), handle, false);
if (element == null || !element.exists())
status.merge(ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), ID_EXTRACT_SUPERTYPE));
else
elements.add(element);
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, attribute));
}
fTypesToExtract= (IType[]) elements.toArray(new IType[elements.size()]);
IJavaProject project= null;
if (fMembersToMove.length > 0)
project= fMembersToMove[0].getJavaProject();
fSettings= JavaPreferencesSettings.getCodeGenerationSettings(project);
if (!status.isOK())
return status;
} else
return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
return new RefactoringStatus();
}
/**
* {@inheritDoc}
*/
protected void registerChanges(final TextEditBasedChangeManager manager) throws CoreException {
try {
final ICompilationUnit extractedUnit= getExtractedType().getCompilationUnit().getPrimary();
ICompilationUnit unit= null;
CompilationUnitRewrite rewrite= null;
for (final Iterator iterator= fCompilationUnitRewrites.keySet().iterator(); iterator.hasNext();) {
unit= (ICompilationUnit) iterator.next();
if (!unit.getPrimary().equals(extractedUnit)) {
rewrite= (CompilationUnitRewrite) fCompilationUnitRewrites.get(unit);
if (rewrite != null) {
final CompilationUnitChange layerChange= (CompilationUnitChange) fLayerChanges.get(unit.getPrimary());
final CompilationUnitChange rewriteChange= rewrite.createChange();
if (rewriteChange != null && layerChange != null) {
final MultiStateCompilationUnitChange change= new MultiStateCompilationUnitChange(rewriteChange.getName(), unit);
change.addChange(layerChange);
change.addChange(rewriteChange);
fLayerChanges.remove(unit.getPrimary());
manager.manage(unit, change);
} else if (layerChange != null) {
manager.manage(unit, layerChange);
fLayerChanges.remove(unit.getPrimary());
} else if (rewriteChange != null) {
manager.manage(unit, rewriteChange);
}
}
}
}
for (Iterator iterator= fLayerChanges.entrySet().iterator(); iterator.hasNext();) {
final Map.Entry entry= (Map.Entry) iterator.next();
manager.manage((ICompilationUnit) entry.getKey(), (TextEditBasedChange) entry.getValue());
}
ICompilationUnit[] units= manager.getAllCompilationUnits();
for (int index= 0; index < units.length; index++) {
if (units[index].getPath().equals(extractedUnit.getPath()))
manager.remove(units[index]);
}
} finally {
fLayerChanges.clear();
}
}
/**
* Resets the changes necessary for the working copy layer.
*/
public void resetChanges() {
fLayerChanges.clear();
}
/**
* {@inheritDoc}
*/
protected void rewriteTypeOccurrences(final TextEditBasedChangeManager manager, final CompilationUnitRewrite sourceRewrite, final ICompilationUnit copy, final Set replacements, final RefactoringStatus status, final IProgressMonitor monitor) throws CoreException {
try {
monitor.beginTask("", 20); //$NON-NLS-1$
monitor.setTaskName(RefactoringCoreMessages.ExtractSupertypeProcessor_checking);
try {
final IType declaring= getDeclaringType();
final ICompilationUnit destinationUnit= getDestinationType().getCompilationUnit();
final IJavaProject project= declaring.getJavaProject();
final ASTParser parser= ASTParser.newParser(AST.JLS3);
parser.setWorkingCopyOwner(fOwner);
parser.setResolveBindings(true);
parser.setProject(project);
parser.setCompilerOptions(RefactoringASTParser.getCompilerOptions(project));
parser.createASTs(new ICompilationUnit[] { copy}, new String[0], new ASTRequestor() {
public final void acceptAST(final ICompilationUnit unit, final CompilationUnit node) {
try {
final IType subType= (IType) JavaModelUtil.findInCompilationUnit(unit, declaring);
final AbstractTypeDeclaration subDeclaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(subType, node);
if (subDeclaration != null) {
final ITypeBinding subBinding= subDeclaration.resolveBinding();
if (subBinding != null) {
String name= null;
ITypeBinding superBinding= null;
final ITypeBinding[] superBindings= Bindings.getAllSuperTypes(subBinding);
for (int index= 0; index < superBindings.length; index++) {
name= superBindings[index].getName();
if (name.startsWith(fDestinationType.getElementName()))
superBinding= superBindings[index];
}
if (superBinding != null) {
solveSuperTypeConstraints(unit, node, subType, subBinding, superBinding, new SubProgressMonitor(monitor, 14), status);
if (!status.hasFatalError())
rewriteTypeOccurrences(manager, this, sourceRewrite, unit, node, replacements, status, new SubProgressMonitor(monitor, 3));
if (manager.containsChangesIn(destinationUnit)) {
final TextEditBasedChange change= manager.get(destinationUnit);
if (change instanceof TextChange) {
final TextEdit edit= ((TextChange) change).getEdit();
if (edit != null) {
final IDocument document= new Document(destinationUnit.getBuffer().getContents());
try {
edit.apply(document, TextEdit.UPDATE_REGIONS);
} catch (MalformedTreeException exception) {
JavaPlugin.log(exception);
status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractSupertypeProcessor_unexpected_exception));
} catch (BadLocationException exception) {
JavaPlugin.log(exception);
status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractSupertypeProcessor_unexpected_exception));
}
fSuperSource= document.get();
manager.remove(destinationUnit);
}
}
}
}
}
}
} catch (JavaModelException exception) {
JavaPlugin.log(exception);
status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractSupertypeProcessor_unexpected_exception));
}
}
public final void acceptBinding(final String key, final IBinding binding) {
// Do nothing
}
}, new SubProgressMonitor(monitor, 1));
} finally {
}
} finally {
monitor.done();
}
}
/**
* Sets the type name.
*
* @param name
* the type name
*/
public void setTypeName(final String name) {
Assert.isNotNull(name);
fTypeName= name;
}
/**
* Sets the types to extract. Must be a subset of
* <code>getPossibleCandidates()</code>. If the declaring type is not
* contained, it will automatically be added.
*
* @param types
* the types to extract
*/
public void setTypesToExtract(final IType[] types) {
Assert.isNotNull(types);
fTypesToExtract= types;
}
}