blob: 997014c48cccf93176188ddd8dbbb55d96794d8f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2008 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.core.refactoring.descriptors;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.ltk.core.refactoring.RefactoringContribution;
import org.eclipse.ltk.core.refactoring.RefactoringCore;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
import org.eclipse.jdt.internal.core.refactoring.descriptors.DescriptorMessages;
import org.eclipse.jdt.internal.core.refactoring.descriptors.JavaRefactoringDescriptorUtil;
/**
* Refactoring descriptor for the rename java element refactoring.
* <p>
* An instance of this refactoring descriptor may be obtained by calling
* {@link RefactoringContribution#createDescriptor()} on a refactoring
* contribution requested by invoking
* {@link RefactoringCore#getRefactoringContribution(String)} with the
* appropriate refactoring id.
* </p>
* <p>
* Note: this class is not intended to be instantiated by clients.
* </p>
*
* @since 1.1
*
* @noinstantiate This class is not intended to be instantiated by clients.
* @noextend This class is not intended to be subclassed by clients.
*/
public final class RenameJavaElementDescriptor extends JavaRefactoringDescriptor {
/** The delegate attribute */
private static final String ATTRIBUTE_DELEGATE= "delegate"; //$NON-NLS-1$
/** The deprecate attribute */
private static final String ATTRIBUTE_DEPRECATE= "deprecate"; //$NON-NLS-1$
/** The hierarchical attribute */
private static final String ATTRIBUTE_HIERARCHICAL= "hierarchical"; //$NON-NLS-1$
/** The match strategy attribute */
private static final String ATTRIBUTE_MATCH_STRATEGY= "matchStrategy"; //$NON-NLS-1$
/** The parameter attribute */
private static final String ATTRIBUTE_PARAMETER= "parameter"; //$NON-NLS-1$
/** The patterns attribute */
private static final String ATTRIBUTE_PATTERNS= "patterns"; //$NON-NLS-1$
/** The qualified attribute */
private static final String ATTRIBUTE_QUALIFIED= "qualified"; //$NON-NLS-1$
/** The rename getter attribute */
private static final String ATTRIBUTE_RENAME_GETTER= "getter"; //$NON-NLS-1$
/** The rename setter attribute */
private static final String ATTRIBUTE_RENAME_SETTER= "setter"; //$NON-NLS-1$
/** The similar declarations attribute */
private static final String ATTRIBUTE_SIMILAR_DECLARATIONS= "similarDeclarations"; //$NON-NLS-1$
/** The textual matches attribute */
private static final String ATTRIBUTE_TEXTUAL_MATCHES= "textual"; //$NON-NLS-1$
/**
* Similar declaration updating strategy which finds exact names and
* embedded names as well (value: <code>2</code>).
*/
public static final int STRATEGY_EMBEDDED= 2;
/**
* Similar declaration updating strategy which finds exact names only
* (value: <code>1</code>).
*/
public static final int STRATEGY_EXACT= 1;
/**
* Similar declaration updating strategy which finds exact names, embedded
* names and name suffixes (value: <code>3</code>).
*/
public static final int STRATEGY_SUFFIX= 3;
/** @deprecated */
private static final String RENAME_RESOURCE= IJavaRefactorings.RENAME_RESOURCE;
/** The delegate attribute */
private boolean fDelegate= false;
/** The deprecate attribute */
private boolean fDeprecate= false;
/** The hierarchical attribute */
private boolean fHierarchical= false;
/**
* The java element attribute.
* WARNING: may not exist, see comment in
* {@link JavaRefactoringDescriptorUtil#handleToElement(org.eclipse.jdt.core.WorkingCopyOwner, String, String, boolean)}.
*/
private IJavaElement fJavaElement= null;
/** The match strategy */
private int fMatchStrategy= STRATEGY_EXACT;
/** The name attribute */
private String fName= null;
/** The patterns attribute */
private String fPatterns= null;
/** The qualified attribute */
private boolean fQualified= false;
/** The references attribute */
private boolean fReferences= false;
/** The rename getter attribute */
private boolean fRenameGetter= false;
/** The rename setter attribute */
private boolean fRenameSetter= false;
/** The similar declarations attribute */
private boolean fSimilarDeclarations= false;
/** The textual attribute */
private boolean fTextual= false;
/**
* Creates a new refactoring descriptor.
*
* @param id
* the unique id of the rename refactoring
* @see IJavaRefactorings
*/
public RenameJavaElementDescriptor(final String id) {
super(id);
Assert.isLegal(checkId(id), "Refactoring id is not a rename refactoring id"); //$NON-NLS-1$
}
/**
* Creates a new refactoring descriptor.
*
* @param id
* the ID of this descriptor
* @param project
* the non-empty name of the project associated with this
* refactoring, or <code>null</code> for a workspace
* refactoring
* @param description
* a non-empty human-readable description of the particular
* refactoring instance
* @param comment
* the human-readable comment of the particular refactoring
* instance, or <code>null</code> for no comment
* @param arguments
* a map of arguments that will be persisted and describes
* all settings for this refactoring
* @param flags
* the flags of the refactoring descriptor
*
* @throws IllegalArgumentException if the argument map contains invalid keys/values
*
* @since 1.2
*/
public RenameJavaElementDescriptor(String id, String project, String description, String comment, Map arguments, int flags) {
super(id, project, description, comment, arguments, flags);
Assert.isLegal(checkId(id), "Refactoring id is not a rename refactoring id"); //$NON-NLS-1$
fName= JavaRefactoringDescriptorUtil.getString(fArguments, ATTRIBUTE_NAME);
if (getID().equals(IJavaRefactorings.RENAME_TYPE_PARAMETER)) {
fJavaElement= JavaRefactoringDescriptorUtil.getJavaElement(fArguments, ATTRIBUTE_INPUT, getProject());
String parameterName= JavaRefactoringDescriptorUtil.getString(fArguments, ATTRIBUTE_PARAMETER);
if (fJavaElement instanceof IType) {
fJavaElement= ((IType) fJavaElement).getTypeParameter(parameterName);
}
if (fJavaElement instanceof IMethod) {
fJavaElement=((IMethod) fJavaElement).getTypeParameter(parameterName);
}
} else
fJavaElement= JavaRefactoringDescriptorUtil.getJavaElement(fArguments, ATTRIBUTE_INPUT, getProject());
final int type= fJavaElement.getElementType();
if (type != IJavaElement.PACKAGE_FRAGMENT_ROOT)
fReferences= JavaRefactoringDescriptorUtil.getBoolean(fArguments, ATTRIBUTE_REFERENCES, fReferences);
if (type == IJavaElement.FIELD) {
fRenameGetter= JavaRefactoringDescriptorUtil.getBoolean(fArguments, ATTRIBUTE_RENAME_GETTER, fRenameGetter);
fRenameSetter= JavaRefactoringDescriptorUtil.getBoolean(fArguments, ATTRIBUTE_RENAME_SETTER, fRenameSetter);
}
switch (type) {
case IJavaElement.PACKAGE_FRAGMENT:
case IJavaElement.TYPE:
case IJavaElement.FIELD:
fTextual= JavaRefactoringDescriptorUtil.getBoolean(fArguments, ATTRIBUTE_TEXTUAL_MATCHES, fTextual);
break;
default:
break;
}
switch (type) {
case IJavaElement.METHOD:
case IJavaElement.FIELD:
fDeprecate= JavaRefactoringDescriptorUtil.getBoolean(fArguments, ATTRIBUTE_DEPRECATE, fDeprecate);
fDelegate= JavaRefactoringDescriptorUtil.getBoolean(fArguments, ATTRIBUTE_DELEGATE, fDelegate);
break;
default:
break;
}
switch (type) {
case IJavaElement.PACKAGE_FRAGMENT:
case IJavaElement.TYPE:
fQualified= JavaRefactoringDescriptorUtil.getBoolean(fArguments, ATTRIBUTE_QUALIFIED, fQualified);
fPatterns= JavaRefactoringDescriptorUtil.getString(fArguments, ATTRIBUTE_PATTERNS, true);
break;
default:
break;
}
switch (type) {
case IJavaElement.TYPE:
fSimilarDeclarations= JavaRefactoringDescriptorUtil.getBoolean(fArguments, ATTRIBUTE_SIMILAR_DECLARATIONS, fSimilarDeclarations);
fMatchStrategy= JavaRefactoringDescriptorUtil.getInt(fArguments, ATTRIBUTE_MATCH_STRATEGY, fMatchStrategy);
break;
default:
break;
}
switch (type) {
case IJavaElement.PACKAGE_FRAGMENT:
fHierarchical= JavaRefactoringDescriptorUtil.getBoolean(fArguments, ATTRIBUTE_HIERARCHICAL, fHierarchical);
break;
default:
break;
}
}
/**
* Checks whether the refactoring id is valid.
*
* @param id
* the refactoring id
* @return the outcome of the validation
*/
private boolean checkId(final String id) {
Assert.isNotNull(id);
if (id.equals(IJavaRefactorings.RENAME_COMPILATION_UNIT))
return true;
else if (id.equals(IJavaRefactorings.RENAME_ENUM_CONSTANT))
return true;
else if (id.equals(IJavaRefactorings.RENAME_FIELD))
return true;
else if (id.equals(IJavaRefactorings.RENAME_JAVA_PROJECT))
return true;
else if (id.equals(IJavaRefactorings.RENAME_LOCAL_VARIABLE))
return true;
else if (id.equals(IJavaRefactorings.RENAME_METHOD))
return true;
else if (id.equals(IJavaRefactorings.RENAME_PACKAGE))
return true;
else if (id.equals(RENAME_RESOURCE))
return true;
else if (id.equals(IJavaRefactorings.RENAME_SOURCE_FOLDER))
return true;
else if (id.equals(IJavaRefactorings.RENAME_TYPE))
return true;
else if (id.equals(IJavaRefactorings.RENAME_TYPE_PARAMETER))
return true;
return false;
}
/**
* {@inheritDoc}
*/
protected void populateArgumentMap() {
super.populateArgumentMap();
JavaRefactoringDescriptorUtil.setString(fArguments, ATTRIBUTE_NAME, fName);
if (getID().equals(IJavaRefactorings.RENAME_TYPE_PARAMETER)) {
final ITypeParameter parameter= (ITypeParameter) fJavaElement;
JavaRefactoringDescriptorUtil.setJavaElement(fArguments, ATTRIBUTE_INPUT, getProject(), parameter.getDeclaringMember());
JavaRefactoringDescriptorUtil.setString(fArguments, ATTRIBUTE_PARAMETER, parameter.getElementName());
} else
JavaRefactoringDescriptorUtil.setJavaElement(fArguments, ATTRIBUTE_INPUT, getProject(), fJavaElement);
final int type= fJavaElement.getElementType();
if (type != IJavaElement.PACKAGE_FRAGMENT_ROOT)
JavaRefactoringDescriptorUtil.setBoolean(fArguments, ATTRIBUTE_REFERENCES, fReferences);
if (type == IJavaElement.FIELD) {
JavaRefactoringDescriptorUtil.setBoolean(fArguments, ATTRIBUTE_RENAME_GETTER, fRenameGetter);
JavaRefactoringDescriptorUtil.setBoolean(fArguments, ATTRIBUTE_RENAME_SETTER, fRenameSetter);
}
switch (type) {
case IJavaElement.PACKAGE_FRAGMENT:
case IJavaElement.TYPE:
case IJavaElement.FIELD:
JavaRefactoringDescriptorUtil.setBoolean(fArguments, ATTRIBUTE_TEXTUAL_MATCHES, fTextual);
break;
default:
break;
}
switch (type) {
case IJavaElement.METHOD:
case IJavaElement.FIELD:
JavaRefactoringDescriptorUtil.setBoolean(fArguments, ATTRIBUTE_DEPRECATE, fDeprecate);
JavaRefactoringDescriptorUtil.setBoolean(fArguments, ATTRIBUTE_DELEGATE, fDelegate);
break;
default:
break;
}
switch (type) {
case IJavaElement.PACKAGE_FRAGMENT:
case IJavaElement.TYPE:
JavaRefactoringDescriptorUtil.setBoolean(fArguments, ATTRIBUTE_QUALIFIED, fQualified);
JavaRefactoringDescriptorUtil.setString(fArguments, ATTRIBUTE_PATTERNS, fPatterns);
break;
default:
break;
}
switch (type) {
case IJavaElement.TYPE:
JavaRefactoringDescriptorUtil.setBoolean(fArguments, ATTRIBUTE_SIMILAR_DECLARATIONS, fSimilarDeclarations);
JavaRefactoringDescriptorUtil.setInt(fArguments, ATTRIBUTE_MATCH_STRATEGY, fMatchStrategy);
break;
default:
break;
}
switch (type) {
case IJavaElement.PACKAGE_FRAGMENT:
JavaRefactoringDescriptorUtil.setBoolean(fArguments, ATTRIBUTE_HIERARCHICAL, fHierarchical);
break;
default:
break;
}
}
/**
* Determines whether the delegate for a Java element should be declared as
* deprecated.
* <p>
* Note: Deprecation of the delegate is currently applicable to the Java elements
* {@link IMethod} and {@link IField}. The default is to not deprecate the
* delegate.
* </p>
*
* @param deprecate
* <code>true</code> to deprecate the delegate,
* <code>false</code> otherwise
*/
public void setDeprecateDelegate(final boolean deprecate) {
fDeprecate= deprecate;
}
/**
* Sets the file name patterns to use during qualified name updating.
* <p>
* The syntax of the file name patterns is a sequence of individual name
* patterns, separated by comma. Additionally, wildcard characters '*' (any
* string) and '?' (any character) may be used.
* </p>
* <p>
* Note: If file name patterns are set, qualified name updating must be
* enabled by calling {@link #setUpdateQualifiedNames(boolean)}.
* </p>
* <p>
* Note: Qualified name updating is currently applicable to the Java elements
* {@link IPackageFragment} and {@link IType}. The default is to use no
* file name patterns (meaning that all files are processed).
* </p>
*
* @param patterns
* the non-empty file name patterns string
*/
public void setFileNamePatterns(final String patterns) {
Assert.isNotNull(patterns);
Assert.isLegal(!"".equals(patterns), "Pattern must not be empty"); //$NON-NLS-1$ //$NON-NLS-2$
fPatterns= patterns;
}
/**
* Sets the Java element to be renamed.
* <p>
* Note: If the Java element to be renamed is of type
* {@link IJavaElement#JAVA_PROJECT}, clients are required to to set the
* project name to <code>null</code>.
* </p>
*
* @param element
* the Java element to be renamed
*/
public void setJavaElement(final IJavaElement element) {
Assert.isNotNull(element);
fJavaElement= element;
}
/**
* Determines whether the the original Java element should be kept as
* delegate to the renamed one.
* <p>
* Note: Keeping of original elements as delegates is currently applicable to the Java
* elements {@link IMethod} and {@link IField}. The default is to not keep
* the original as delegate.
* </p>
*
* @param delegate
* <code>true</code> to keep the original, <code>false</code>
* otherwise
*/
public void setKeepOriginal(final boolean delegate) {
fDelegate= delegate;
}
/**
* Determines which strategy should be used during similar declaration
* updating.
* <p>
* Valid arguments are {@link #STRATEGY_EXACT}, {@link #STRATEGY_EMBEDDED}
* or {@link #STRATEGY_SUFFIX}.
* </p>
* <p>
* Note: Similar declaration updating is currently applicable to Java elements of type
* {@link IType}. The default is to use the {@link #STRATEGY_EXACT} match
* strategy.
* </p>
*
* @param strategy
* the match strategy to use
*/
public void setMatchStrategy(final int strategy) {
Assert.isLegal(strategy == STRATEGY_EXACT || strategy == STRATEGY_EMBEDDED || strategy == STRATEGY_SUFFIX, "Wrong match strategy argument"); //$NON-NLS-1$
fMatchStrategy= strategy;
}
/**
* Sets the new name to rename the Java element to.
*
* @param name
* the non-empty new name to set
*/
public void setNewName(final String name) {
Assert.isNotNull(name);
Assert.isLegal(!"".equals(name), "Name must not be empty"); //$NON-NLS-1$//$NON-NLS-2$
fName= name;
}
/**
* Sets the project name of this refactoring.
* <p>
* Note: If the Java element to be renamed is of type
* {@link IJavaElement#JAVA_PROJECT}, clients are required to to set the
* project name to <code>null</code>.
* </p>
* <p>
* The default is to associate the refactoring with the workspace.
* </p>
*
* @param project
* the non-empty project name to set, or <code>null</code> for
* the workspace
*
* @see #getProject()
*/
public void setProject(final String project) {
super.setProject(project);
}
/**
* Determines whether getter methods for the Java element should be renamed.
* <p>
* Note: Renaming of getter methods is applicable for {@link IField}
* elements which do not represent enum constants only. The default is to
* not rename any getter methods.
* </p>
*
* @param rename
* <code>true</code> to rename getter methods,
* <code>false</code> otherwise
*/
public void setRenameGetters(final boolean rename) {
fRenameGetter= rename;
}
/**
* Determines whether setter methods for the Java element should be renamed.
* <p>
* Note: Renaming of setter methods is applicable for {@link IField}
* elements which do not represent enum constants only. The default is to
* not rename any setter methods.
* </p>
*
* @param rename
* <code>true</code> to rename setter methods,
* <code>false</code> otherwise
*/
public void setRenameSetters(final boolean rename) {
fRenameSetter= rename;
}
/**
* Determines whether other Java elements in the hierarchy of the input
* element should be renamed as well.
* <p>
* Note: Hierarchical updating is currently applicable for Java elements of
* type {@link IPackageFragment}. The default is to not update Java
* elements hierarchically.
* </p>
*
* @param update
* <code>true</code> to update hierarchically,
* <code>false</code> otherwise
*/
public void setUpdateHierarchy(final boolean update) {
fHierarchical= update;
}
/**
* Determines whether qualified names of the Java element should be renamed.
* <p>
* Qualified name updating adapts fully qualified names of the Java element
* to be renamed in non-Java text files. Clients may specify file name
* patterns by calling {@link #setFileNamePatterns(String)} to constrain the
* set of text files to be processed.
* </p>
* <p>
* Note: Qualified name updating is currently applicable to the Java elements
* {@link IPackageFragment} and {@link IType}. The default is to not rename
* qualified names.
* </p>
*
* @param update
* <code>true</code> to update qualified names,
* <code>false</code> otherwise
*/
public void setUpdateQualifiedNames(final boolean update) {
fQualified= update;
}
/**
* Determines whether references to the Java element should be renamed.
* <p>
* Note: Reference updating is currently applicable to all Java element types except
* {@link IPackageFragmentRoot}. The default is to not update references.
* </p>
*
* @param update
* <code>true</code> to update references, <code>false</code>
* otherwise
*/
public void setUpdateReferences(final boolean update) {
fReferences= update;
}
/**
* Determines whether similar declarations of the Java element should be
* updated.
* <p>
* Note: Similar declaration updating is currently applicable to Java elements of type
* {@link IType}. The default is to not update similar declarations.
* </p>
*
* @param update
* <code>true</code> to update similar declarations,
* <code>false</code> otherwise
*/
public void setUpdateSimilarDeclarations(final boolean update) {
fSimilarDeclarations= update;
}
/**
* Determines whether textual occurrences of the Java element should be
* renamed.
* <p>
* Textual occurrence updating adapts textual occurrences of the Java
* element to be renamed in Java comments and Java strings.
* </p>
* <p>
* Note: Textual occurrence updating is currently applicable to the Java elements
* {@link IPackageFragment}, {@link IType} and {@link IField}. The default
* is to not rename textual occurrences.
* </p>
*
* @param update
* <code>true</code> to update occurrences, <code>false</code>
* otherwise
*/
public void setUpdateTextualOccurrences(final boolean update) {
fTextual= update;
}
/**
* {@inheritDoc}
*/
public RefactoringStatus validateDescriptor() {
RefactoringStatus status= super.validateDescriptor();
if (fName == null || "".equals(fName)) //$NON-NLS-1$
status.merge(RefactoringStatus.createFatalErrorStatus(DescriptorMessages.RenameResourceDescriptor_no_new_name));
if (fJavaElement == null)
status.merge(RefactoringStatus.createFatalErrorStatus(DescriptorMessages.RenameJavaElementDescriptor_no_java_element));
else {
final int type= fJavaElement.getElementType();
if (type == IJavaElement.JAVA_PROJECT && getProject() != null)
status.merge(RefactoringStatus.createFatalErrorStatus(DescriptorMessages.RenameJavaElementDescriptor_project_constraint));
if (type == IJavaElement.PACKAGE_FRAGMENT_ROOT && fReferences)
status.merge(RefactoringStatus.createFatalErrorStatus(DescriptorMessages.RenameJavaElementDescriptor_reference_constraint));
if (fTextual) {
switch (type) {
case IJavaElement.PACKAGE_FRAGMENT:
case IJavaElement.TYPE:
case IJavaElement.FIELD:
break;
default:
status.merge(RefactoringStatus.createFatalErrorStatus(DescriptorMessages.RenameJavaElementDescriptor_textual_constraint));
}
}
if (fDeprecate) {
switch (type) {
case IJavaElement.METHOD:
case IJavaElement.FIELD:
break;
default:
status.merge(RefactoringStatus.createFatalErrorStatus(DescriptorMessages.RenameJavaElementDescriptor_deprecation_constraint));
}
}
if (fDelegate) {
switch (type) {
case IJavaElement.METHOD:
case IJavaElement.FIELD:
break;
default:
status.merge(RefactoringStatus.createFatalErrorStatus(DescriptorMessages.RenameJavaElementDescriptor_delegate_constraint));
}
}
if (fRenameGetter || fRenameSetter) {
if (type != IJavaElement.FIELD)
status.merge(RefactoringStatus.createFatalErrorStatus(DescriptorMessages.RenameJavaElementDescriptor_accessor_constraint));
}
if (fQualified) {
switch (type) {
case IJavaElement.PACKAGE_FRAGMENT:
case IJavaElement.TYPE:
break;
default:
status.merge(RefactoringStatus.createFatalErrorStatus(DescriptorMessages.RenameJavaElementDescriptor_qualified_constraint));
}
}
if (fSimilarDeclarations) {
switch (type) {
case IJavaElement.TYPE:
break;
default:
status.merge(RefactoringStatus.createFatalErrorStatus(DescriptorMessages.RenameJavaElementDescriptor_similar_constraint));
}
}
if (fHierarchical) {
switch (type) {
case IJavaElement.PACKAGE_FRAGMENT:
break;
default:
status.merge(RefactoringStatus.createFatalErrorStatus(DescriptorMessages.RenameJavaElementDescriptor_hierarchical_constraint));
}
}
}
return status;
}
}