/*******************************************************************************
 * Copyright (c) 2000, 2011 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
 *     Matt Chapman, mpchapman@gmail.com - 89977 Make JDT .java agnostic
 *******************************************************************************/
package org.eclipse.jdt.internal.corext.refactoring.rename;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IProduct;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SubProgressMonitor;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;

import org.eclipse.text.edits.ReplaceEdit;

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.IResourceMapper;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
import org.eclipse.ltk.core.refactoring.TextChange;
import org.eclipse.ltk.core.refactoring.TextFileChange;
import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
import org.eclipse.ltk.core.refactoring.participants.IParticipantDescriptorFilter;
import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
import org.eclipse.ltk.core.refactoring.participants.RenameArguments;
import org.eclipse.ltk.core.refactoring.resource.RenameResourceChange;

import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.refactoring.IJavaElementMapper;
import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
import org.eclipse.jdt.core.refactoring.RenameTypeArguments;
import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
import org.eclipse.jdt.core.refactoring.descriptors.RenameJavaElementDescriptor;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.TypeReferenceMatch;

import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory;
import org.eclipse.jdt.internal.corext.refactoring.Checks;
import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine;
import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
import org.eclipse.jdt.internal.corext.refactoring.base.ReferencesInBinaryContext;
import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
import org.eclipse.jdt.internal.corext.refactoring.changes.RenameCompilationUnitChange;
import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility;
import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors;
import org.eclipse.jdt.internal.corext.refactoring.tagging.IQualifiedNameUpdating;
import org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating;
import org.eclipse.jdt.internal.corext.refactoring.tagging.ISimilarDeclarationUpdating;
import org.eclipse.jdt.internal.corext.refactoring.tagging.ITextUpdating;
import org.eclipse.jdt.internal.corext.refactoring.util.Changes;
import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
import org.eclipse.jdt.internal.corext.refactoring.util.QualifiedNameFinder;
import org.eclipse.jdt.internal.corext.refactoring.util.QualifiedNameSearchResult;
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.TextChangeManager;
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.internal.corext.util.SearchUtils;

import org.eclipse.jdt.ui.JavaElementLabels;
import org.eclipse.jdt.ui.refactoring.IRefactoringProcessorIds;
import org.eclipse.jdt.ui.refactoring.RefactoringSaveHelper;

import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;

public class RenameTypeProcessor extends JavaRenameProcessor implements ITextUpdating, IReferenceUpdating, IQualifiedNameUpdating, ISimilarDeclarationUpdating, IResourceMapper, IJavaElementMapper {

	private static final String ATTRIBUTE_QUALIFIED= "qualified"; //$NON-NLS-1$
	private static final String ATTRIBUTE_TEXTUAL_MATCHES= "textual"; //$NON-NLS-1$
	private static final String ATTRIBUTE_PATTERNS= "patterns"; //$NON-NLS-1$
	private static final String ATTRIBUTE_SIMILAR_DECLARATIONS= "similarDeclarations"; //$NON-NLS-1$
	private static final String ATTRIBUTE_MATCHING_STRATEGY= "matchStrategy"; //$NON-NLS-1$

    private static final GroupCategorySet CATEGORY_TYPE_RENAME= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.refactoring.rename.renameType.type", RefactoringCoreMessages.RenameTypeProcessor_changeCategory_type, RefactoringCoreMessages.RenameTypeProcessor_changeCategory_type_description)); //$NON-NLS-1$
    private static final GroupCategorySet CATEGORY_METHOD_RENAME= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.refactoring.rename.renameType.method", RefactoringCoreMessages.RenameTypeProcessor_changeCategory_method, RefactoringCoreMessages.RenameTypeProcessor_changeCategory_method_description)); //$NON-NLS-1$
    private static final GroupCategorySet CATEGORY_FIELD_RENAME= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.refactoring.rename.renameType.field", RefactoringCoreMessages.RenameTypeProcessor_changeCategory_fields, RefactoringCoreMessages.RenameTypeProcessor_changeCategory_fields_description)); //$NON-NLS-1$
    private static final GroupCategorySet CATEGORY_LOCAL_RENAME= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.refactoring.rename.renameType.local", RefactoringCoreMessages.RenameTypeProcessor_changeCategory_local_variables, RefactoringCoreMessages.RenameTypeProcessor_changeCategory_local_variables_description)); //$NON-NLS-1$

	private IType fType;
	private SearchResultGroup[] fReferences;
	private TextChangeManager fChangeManager;
	private QualifiedNameSearchResult fQualifiedNameSearchResult;

	private boolean fUpdateReferences;

	private boolean fUpdateTextualMatches;

	private boolean fUpdateQualifiedNames;
	private String fFilePatterns;

	// --- similar elements

	private boolean fUpdateSimilarElements;
	private Map<IJavaElement, String> fFinalSimilarElementToName= null;
	private int fRenamingStrategy;

	// Preloaded information for the UI.
	private LinkedHashMap<IJavaElement, String> fPreloadedElementToName= null;
	private Map<IJavaElement, Boolean> fPreloadedElementToSelection= null;
	private LinkedHashMap<IJavaElement, String> fPreloadedElementToNameDefault= null;

	// Cache information to decide whether to
	// re-update references and preload info
	private String fCachedNewName= null;
	private boolean fCachedRenameSimilarElements= false;
	private int fCachedRenamingStrategy= -1;
	private RefactoringStatus fCachedRefactoringStatus= null;

	public static final class ParticipantDescriptorFilter implements IParticipantDescriptorFilter {

		public boolean select(IConfigurationElement element, RefactoringStatus status) {
			IConfigurationElement[] params= element.getChildren(PARAM);
			for (int i= 0; i < params.length; i++) {
				IConfigurationElement param= params[i];
				if ("handlesSimilarDeclarations".equals(param.getAttribute(NAME)) && //$NON-NLS-1$
						"false".equals(param.getAttribute(VALUE))) { //$NON-NLS-1$
					return false;
				}
			}
			return true;
		}
	}

	private class NoOverrideProgressMonitor extends SubProgressMonitor {
		public NoOverrideProgressMonitor(IProgressMonitor monitor, int ticks) {
			super(monitor, ticks, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL);
		}
		@Override
		public void setTaskName(String name) {
			// do nothing
		}
	}

	/**
	 * Creates a new rename type processor.
	 * @param type the type, or <code>null</code> if invoked by scripting
	 */
	public RenameTypeProcessor(IType type) {
		fType= type;
		if (type != null)
			setNewElementName(type.getElementName());
		fUpdateReferences= true; //default is yes
		fUpdateTextualMatches= false;
		fUpdateSimilarElements= false; // default is no
		fRenamingStrategy= RenamingNameSuggestor.STRATEGY_EXACT;
	}

	public RenameTypeProcessor(JavaRefactoringArguments arguments, RefactoringStatus status) {
		this(null);
		status.merge(initialize(arguments));
	}

	public IType getType() {
		return fType;
	}

	@Override
	public String getIdentifier() {
		return IRefactoringProcessorIds.RENAME_TYPE_PROCESSOR;
	}

	@Override
	public boolean isApplicable() throws CoreException {
		return RefactoringAvailabilityTester.isRenameAvailable(fType);
	}

	@Override
	public String getProcessorName() {
		return RefactoringCoreMessages.RenameTypeRefactoring_name;
	}

	@Override
	protected String[] getAffectedProjectNatures() throws CoreException {
		return JavaProcessors.computeAffectedNatures(fType);
	}

	@Override
	public Object[] getElements() {
		return new Object[] {fType};
	}

	@Override
	protected RenameModifications computeRenameModifications() {
		RenameModifications result= new RenameModifications();
		result.rename(fType, new RenameTypeArguments(getNewElementName(), getUpdateReferences(),
			getUpdateSimilarDeclarations(), getSimilarElements()), createParticipantDescriptorFilter());
		if (isPrimaryType()) {
			ICompilationUnit cu= fType.getCompilationUnit();
			String newCUName= getNewCompilationUnit().getElementName();
			result.rename(cu, new RenameArguments(newCUName, getUpdateReferences()));
		}
		return result;
	}

	/*
	 * Note: this is a handle-only method!
	 */
	private boolean isPrimaryType() {
		String cuName= fType.getCompilationUnit().getElementName();
		String typeName= fType.getElementName();
		return Checks.isTopLevel(fType) && JavaCore.removeJavaLikeExtension(cuName).equals(typeName);
	}

	//---- IRenameProcessor ----------------------------------------------

	public String getCurrentElementName(){
		return fType.getElementName();
	}

	public String getCurrentElementQualifier(){
		return JavaModelUtil.getTypeContainerName(fType);
	}

	public RefactoringStatus checkNewElementName(String newName){
		Assert.isNotNull(newName, "new name"); //$NON-NLS-1$
		RefactoringStatus result= Checks.checkTypeName(newName, fType);
		if (Checks.isAlreadyNamed(fType, newName))
			result.addFatalError(RefactoringCoreMessages.RenameTypeRefactoring_choose_another_name);
		return result;
	}

	public Object getNewElement() {
		if (Checks.isTopLevel(fType)) {
			return getNewCompilationUnit().getType(getNewElementName());
		} else {
			return fType.getDeclaringType().getType(getNewElementName());
		}
	}

	private ICompilationUnit getNewCompilationUnit() {
		ICompilationUnit cu= fType.getCompilationUnit();
		if (isPrimaryType()) {
			IPackageFragment parent= fType.getPackageFragment();
			String renamedCUName= JavaModelUtil.getRenamedCUName(cu, getNewElementName());
			return parent.getCompilationUnit(renamedCUName);
		} else {
			return cu;
		}
	}

	//---- JavaRenameProcessor -------------------------------------------

	protected RenameArguments createRenameArguments() {
		return new RenameTypeArguments(getNewElementName(), getUpdateReferences(),
			getUpdateSimilarDeclarations(), getSimilarElements());
	}

	protected IParticipantDescriptorFilter createParticipantDescriptorFilter() {
		if (!getUpdateSimilarDeclarations())
			return null;
		return new ParticipantDescriptorFilter();
	}

	@Override
	protected IFile[] getChangedFiles() throws CoreException {
		List<IFile> result= new ArrayList<IFile>();
		result.addAll(Arrays.asList(ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits())));
		if (fQualifiedNameSearchResult != null)
			result.addAll(Arrays.asList(fQualifiedNameSearchResult.getAllFiles()));
		if (willRenameCU())
			result.add(ResourceUtil.getFile(fType.getCompilationUnit()));
		return result.toArray(new IFile[result.size()]);
	}

	@Override
	public int getSaveMode() {
		return RefactoringSaveHelper.SAVE_REFACTORING;
	}

	//---- ITextUpdating -------------------------------------------------

	public boolean canEnableTextUpdating() {
		return true;
	}

	public boolean getUpdateTextualMatches() {
		return fUpdateTextualMatches;
	}
	public void setUpdateTextualMatches(boolean update) {
		fUpdateTextualMatches= update;
	}

	//---- IReferenceUpdating --------------------------------------

	public void setUpdateReferences(boolean update){
		fUpdateReferences= update;
	}

	public boolean getUpdateReferences(){
		return fUpdateReferences;
	}

	//---- IQualifiedNameUpdating ----------------------------------

	public boolean canEnableQualifiedNameUpdating() {
		return !fType.getPackageFragment().isDefaultPackage() && !(fType.getParent() instanceof IType);
	}

	public boolean getUpdateQualifiedNames() {
		return fUpdateQualifiedNames;
	}

	public void setUpdateQualifiedNames(boolean update) {
		fUpdateQualifiedNames= update;
	}

	public String getFilePatterns() {
		return fFilePatterns;
	}

	public void setFilePatterns(String patterns) {
		Assert.isNotNull(patterns);
		fFilePatterns= patterns;
	}

	// ---- ISimilarDeclarationUpdating

	public boolean canEnableSimilarDeclarationUpdating() {

		IProduct product= Platform.getProduct();
		if (product != null) {
			String property= product.getProperty("org.eclipse.jdt.ui.refactoring.handlesSimilarDeclarations"); //$NON-NLS-1$
			if ("false".equalsIgnoreCase(property)) //$NON-NLS-1$
				return false;
		}

		return true;
	}

	public void setUpdateSimilarDeclarations(boolean update) {
		fUpdateSimilarElements= update;
	}

	public boolean getUpdateSimilarDeclarations() {
		return fUpdateSimilarElements;
	}

	public int getMatchStrategy() {
		return fRenamingStrategy;

	}

	public void setMatchStrategy(int selectedStrategy) {
		fRenamingStrategy= selectedStrategy;
	}

	/**
	 * @return the similar elements of the type, i.e. IFields, IMethods, and
	 * ILocalVariables. Returns <code>null</code> iff similar declaration updating
	 * is not requested.
	 */
	public IJavaElement[] getSimilarElements() {
		if (fFinalSimilarElementToName == null)
			return null;
		Set<IJavaElement> keys= fFinalSimilarElementToName.keySet();
		return keys.toArray(new IJavaElement[keys.size()]);
	}

	/**
	 * {@inheritDoc}
	 */
	public IResource getRefactoredResource(IResource element) {
		if (element instanceof IFile) {
			if (Checks.isTopLevel(fType) && element.equals(fType.getResource()))
				return getNewCompilationUnit().getResource();
		}
		return element;
	}

	/**
	 * {@inheritDoc}
	 */
	public IJavaElement getRefactoredJavaElement(IJavaElement element) {
		if (element instanceof ICompilationUnit) {
			if (Checks.isTopLevel(fType) && element.equals(fType.getCompilationUnit()))
				return getNewCompilationUnit();
		} else if (element instanceof IMember) {
			final IType newType= (IType) getNewElement();
			final RefactoringHandleTransplanter transplanter= new RefactoringHandleTransplanter(fType, newType, fFinalSimilarElementToName);
			return transplanter.transplantHandle((IMember) element);
		}
		return element;
	}

	@Override
	public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
		IType primary= (IType) fType.getPrimaryElement();
		if (primary == null || !primary.exists()) {
			String qualifiedTypeName= JavaElementLabels.getElementLabel(fType, JavaElementLabels.F_FULLY_QUALIFIED);
			String message= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_does_not_exist, new String[] { BasicElementLabels.getJavaElementName(qualifiedTypeName), BasicElementLabels.getFileName(fType.getCompilationUnit())});
			return RefactoringStatus.createFatalErrorStatus(message);
		}
		fType= primary;
		return Checks.checkIfCuBroken(fType);
	}

	@Override
	protected RefactoringStatus doCheckFinalConditions(IProgressMonitor pm, CheckConditionsContext context) throws CoreException {
		Assert.isNotNull(fType, "type"); //$NON-NLS-1$
		Assert.isNotNull(getNewElementName(), "newName"); //$NON-NLS-1$
		RefactoringStatus result= new RefactoringStatus();

		int referenceSearchTicks= fUpdateReferences || fUpdateSimilarElements ? 15 : 0;
		int affectedCusTicks= fUpdateReferences || fUpdateSimilarElements ? 10 : 1;
		int similarElementTicks= fUpdateSimilarElements ? 85 : 0;
		int createChangeTicks = 5;
		int qualifiedNamesTicks= fUpdateQualifiedNames ? 50 : 0;

		try{
			pm.beginTask("", 12 + referenceSearchTicks + affectedCusTicks + similarElementTicks + createChangeTicks + qualifiedNamesTicks); //$NON-NLS-1$
			pm.setTaskName(RefactoringCoreMessages.RenameTypeRefactoring_checking);

			fChangeManager= new TextChangeManager(true);

			result.merge(checkNewElementName(getNewElementName()));
			if (result.hasFatalError())
				return result;
			result.merge(Checks.checkIfCuBroken(fType));
			if (result.hasFatalError())
				return result;
			pm.worked(1);

			result.merge(checkTypesInCompilationUnit());
			pm.worked(1);

			result.merge(checkForMethodsWithConstructorNames());
			pm.worked(1);

			result.merge(checkImportedTypes());
			pm.worked(1);

			if (Checks.isTopLevel(fType) && (JdtFlags.isPublic(fType)))
				result.merge(Checks.checkCompilationUnitNewName(fType.getCompilationUnit(), getNewElementName()));
			pm.worked(1);

			if (isPrimaryType())
				result.merge(checkNewPathValidity());
			pm.worked(1);

			result.merge(checkEnclosingTypes());
			pm.worked(1);

			result.merge(checkEnclosedTypes());
			pm.worked(1);

			result.merge(checkTypesInPackage());
			pm.worked(1);

			result.merge(checkTypesImportedInCu());
			pm.worked(1);

			result.merge(Checks.checkForMainAndNativeMethods(fType));
			pm.worked(1);

			// before doing any expensive analysis
			if (result.hasFatalError())
				return result;

			result.merge(analyseEnclosedTypes());
			pm.worked(1);
			// before doing _the really_ expensive analysis
			if (result.hasFatalError())
				return result;

			// Load references, including similarly named elements
			if (fUpdateReferences || fUpdateSimilarElements) {
				pm.setTaskName(RefactoringCoreMessages.RenameTypeRefactoring_searching);
				result.merge(initializeReferences(new SubProgressMonitor(pm, referenceSearchTicks)));
			} else {
				fReferences= new SearchResultGroup[0];
			}

			pm.setTaskName(RefactoringCoreMessages.RenameTypeRefactoring_checking);
			if (pm.isCanceled())
				throw new OperationCanceledException();

			if (fUpdateReferences || fUpdateSimilarElements) {
				result.merge(analyzeAffectedCompilationUnits(new SubProgressMonitor(pm, affectedCusTicks)));
			} else {
				Checks.checkCompileErrorsInAffectedFile(result, fType.getResource());
				pm.worked(affectedCusTicks);
			}

			if (result.hasFatalError())
				return result;

			if (fUpdateSimilarElements) {
				result.merge(initializeSimilarElementsRenameProcessors(new SubProgressMonitor(pm, similarElementTicks), context));
				if (result.hasFatalError())
					return result;
			}

			createChanges(new SubProgressMonitor(pm, createChangeTicks));

			if (fUpdateQualifiedNames)
				computeQualifiedNameMatches(new SubProgressMonitor(pm, qualifiedNamesTicks));

			return result;
		} finally {
			pm.done();
		}
	}

	/**
	 * Initializes the references to the type and the similarly named elements. This
	 * method creates both the fReferences and the fPreloadedElementToName
	 * fields.
	 *
	 * May be called from the UI.
	 * @param monitor progress monitor
	 * @return initialization status
	 * @throws JavaModelException some fundamental error with the underlying model
	 * @throws OperationCanceledException if user canceled the task
	 *
	 */
	public RefactoringStatus initializeReferences(IProgressMonitor monitor) throws JavaModelException, OperationCanceledException {

		Assert.isNotNull(fType);
		Assert.isNotNull(getNewElementName());

		// Do not search again if the preconditions have not changed.
		// Search depends on the type, the new name, the similarly named elements, and
		// the strategy

		if (fReferences != null && (getNewElementName().equals(fCachedNewName)) && (fCachedRenameSimilarElements == getUpdateSimilarDeclarations()) && (fCachedRenamingStrategy == fRenamingStrategy))
			return fCachedRefactoringStatus;

		fCachedNewName= getNewElementName();
		fCachedRenameSimilarElements= fUpdateSimilarElements;
		fCachedRenamingStrategy= fRenamingStrategy;
		fCachedRefactoringStatus= new RefactoringStatus();


		try {
			SearchPattern pattern= SearchPattern.createPattern(fType, IJavaSearchConstants.REFERENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);

			String binaryRefsDescription= Messages.format(RefactoringCoreMessages.ReferencesInBinaryContext_ref_in_binaries_description , BasicElementLabels.getJavaElementName(fType.getElementName()));
			ReferencesInBinaryContext binaryRefs= new ReferencesInBinaryContext(binaryRefsDescription);

			fReferences= RefactoringSearchEngine.search(
					pattern,
					RefactoringScopeFactory.create(fType, true, false),
					new TypeOccurrenceCollector(fType, binaryRefs),
					monitor,
					fCachedRefactoringStatus);

			binaryRefs.addErrorIfNecessary(fCachedRefactoringStatus);
			fReferences= Checks.excludeCompilationUnits(fReferences, fCachedRefactoringStatus);

			fPreloadedElementToName= new LinkedHashMap<IJavaElement, String>();
			fPreloadedElementToSelection= new HashMap<IJavaElement, Boolean>();

			final String unQualifiedTypeName= fType.getElementName();

			monitor.beginTask("", fReferences.length); //$NON-NLS-1$

			if (getUpdateSimilarDeclarations()) {

				RenamingNameSuggestor sugg= new RenamingNameSuggestor(fRenamingStrategy);

				for (int i= 0; i < fReferences.length; i++) {
					final ICompilationUnit cu= fReferences[i].getCompilationUnit();
					if (cu == null)
						continue;

					final SearchMatch[] results= fReferences[i].getSearchResults();

					for (int j= 0; j < results.length; j++) {

						if (! (results[j] instanceof TypeReferenceMatch))
							continue;

						final TypeReferenceMatch match= (TypeReferenceMatch) results[j];
						final List<IJavaElement> matches= new ArrayList<IJavaElement>();

						if (match.getLocalElement() != null) {
							if (match.getLocalElement() instanceof ILocalVariable) {
								matches.add(match.getLocalElement());
							}
							// else don't update (e.g. match in type parameter, annotation, ...)
						} else {
							matches.add((IJavaElement) match.getElement());
						}

						final IJavaElement[] others= match.getOtherElements();
						if (others != null)
							matches.addAll(Arrays.asList(others));

						for (Iterator<IJavaElement> iter= matches.iterator(); iter.hasNext();) {
							final IJavaElement element= iter.next();

							if (! (element instanceof IMethod) && ! (element instanceof IField) && ! (element instanceof ILocalVariable))
								continue;

							if (!isInDeclaredType(match.getOffset(), element))
								continue;

							if (element instanceof IField) {
								final IField currentField= (IField) element;
								final String newFieldName= sugg.suggestNewFieldName(currentField.getJavaProject(), currentField.getElementName(), Flags.isStatic(currentField.getFlags()),
										unQualifiedTypeName, getNewElementName());

								if (newFieldName != null)
									fPreloadedElementToName.put(currentField, newFieldName);

							} else if (element instanceof IMethod) {
								final IMethod currentMethod= (IMethod) element;
								addMethodRename(unQualifiedTypeName, sugg, currentMethod);

							} else if (element instanceof ILocalVariable) {
								final ILocalVariable currentLocal= (ILocalVariable) element;
								final boolean isParameter;

								if (currentLocal.isParameter()) {
									addMethodRename(unQualifiedTypeName, sugg, (IMethod) currentLocal.getParent());
									isParameter= true;
								} else
									isParameter= false;

								final String newLocalName= sugg
										.suggestNewLocalName(currentLocal.getJavaProject(), currentLocal.getElementName(), isParameter, unQualifiedTypeName, getNewElementName());

								if (newLocalName != null)
									fPreloadedElementToName.put(currentLocal, newLocalName);
							}
						}
					}
					if (monitor.isCanceled())
						throw new OperationCanceledException();
				}
			}

			for (Iterator<IJavaElement> iter= fPreloadedElementToName.keySet().iterator(); iter.hasNext();) {
				IJavaElement element= iter.next();
				fPreloadedElementToSelection.put(element, Boolean.TRUE);
			}
			fPreloadedElementToNameDefault= (LinkedHashMap<IJavaElement, String>) fPreloadedElementToName.clone();

		} catch (OperationCanceledException e) {
			fReferences= null;
			fPreloadedElementToName= null;
			throw new OperationCanceledException();
		}
		return fCachedRefactoringStatus;
	}

	/**
	 * @param matchOffset offset of the match
	 * @param parentElement parent element of the match
	 * @return true iff the given search match offset (must be a match of a type
	 * reference) lies before the element name of its enclosing java element,
	 * false if not. In other words: If this method returns true, the match is
	 * the declared type (or return type) of the enclosing element.
	 * @throws JavaModelException should not happen
	 *
	 */
	private boolean isInDeclaredType(int matchOffset, IJavaElement parentElement) throws JavaModelException {
		if (parentElement != null) {
			int enclosingNameOffset= 0;
			if (parentElement instanceof IMethod || parentElement instanceof IField)
				enclosingNameOffset= ((IMember) parentElement).getNameRange().getOffset();
			else if (parentElement instanceof ILocalVariable)
				enclosingNameOffset= ((ILocalVariable) parentElement).getNameRange().getOffset();

			return (matchOffset < enclosingNameOffset);
		}
		return false;
	}

	private void addMethodRename(final String unQualifiedTypeName, RenamingNameSuggestor sugg, final IMethod currentMethod) throws JavaModelException {
		if (!currentMethod.isConstructor()) {
			final String newMethodName= sugg.suggestNewMethodName(currentMethod.getElementName(), unQualifiedTypeName, getNewElementName());

			if (newMethodName != null)
				fPreloadedElementToName.put(currentMethod, newMethodName);
		}
	}

	private RefactoringStatus checkNewPathValidity() {
		IContainer c= fType.getCompilationUnit().getResource().getParent();

		String notRename= RefactoringCoreMessages.RenameTypeRefactoring_will_not_rename;
		IStatus status= c.getWorkspace().validateName(getNewElementName(), IResource.FILE);
		if (status.getSeverity() == IStatus.ERROR)
			return RefactoringStatus.createWarningStatus(status.getMessage() + ". " + notRename); //$NON-NLS-1$

		status= c.getWorkspace().validatePath(createNewPath(getNewElementName()), IResource.FILE);
		if (status.getSeverity() == IStatus.ERROR)
			return RefactoringStatus.createWarningStatus(status.getMessage() + ". " + notRename); //$NON-NLS-1$

		return new RefactoringStatus();
	}

	private String createNewPath(String newName) {
		return fType.getCompilationUnit().getResource().getFullPath().removeLastSegments(1).append(newName).toString();
	}

	private RefactoringStatus checkTypesImportedInCu() throws CoreException {
		IImportDeclaration imp= getImportedType(fType.getCompilationUnit(), getNewElementName());

		if (imp == null)
			return null;

		String msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_imported,
											new Object[]{getNewElementLabel(), BasicElementLabels.getPathLabel(fType.getCompilationUnit().getResource().getFullPath(), false)});
		IJavaElement grandParent= imp.getParent().getParent();
		if (grandParent instanceof ICompilationUnit)
			return RefactoringStatus.createErrorStatus(msg, JavaStatusContext.create(imp));

		return null;
	}

	private RefactoringStatus checkTypesInPackage() throws CoreException {
		IType type= Checks.findTypeInPackage(fType.getPackageFragment(), getNewElementName());
		if (type == null || ! type.exists())
			return null;
		String msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_exists,
				new String[] {getNewElementLabel(), JavaElementLabels.getElementLabel(fType.getPackageFragment(), JavaElementLabels.ALL_DEFAULT)});
		return RefactoringStatus.createErrorStatus(msg, JavaStatusContext.create(type));
	}

	private RefactoringStatus checkEnclosedTypes() throws CoreException {
		IType enclosedType= findEnclosedType(fType, getNewElementName());
		if (enclosedType == null)
			return null;
		String msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_encloses,
				new String[] { BasicElementLabels.getJavaElementName(fType.getFullyQualifiedName('.')), getNewElementLabel()});
		return RefactoringStatus.createErrorStatus(msg, JavaStatusContext.create(enclosedType));
	}

	private RefactoringStatus checkEnclosingTypes() {
		IType enclosingType= findEnclosingType(fType, getNewElementName());
		if (enclosingType == null)
			return null;

		String msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_enclosed,
				new String[] { BasicElementLabels.getJavaElementName(fType.getFullyQualifiedName('.')), getNewElementLabel()});
		return RefactoringStatus.createErrorStatus(msg, JavaStatusContext.create(enclosingType));
	}

	private String getNewElementLabel() {
		return BasicElementLabels.getJavaElementName(getNewElementName());
	}

	private static IType findEnclosedType(IType type, String newName) throws CoreException {
		IType[] enclosedTypes= type.getTypes();
		for (int i= 0; i < enclosedTypes.length; i++){
			if (newName.equals(enclosedTypes[i].getElementName()) || findEnclosedType(enclosedTypes[i], newName) != null)
				return enclosedTypes[i];
		}
		return null;
	}

	private static IType findEnclosingType(IType type, String newName) {
		IType enclosing= type.getDeclaringType();
		while (enclosing != null){
			if (newName.equals(enclosing.getElementName()))
				return enclosing;
			else
				enclosing= enclosing.getDeclaringType();
		}
		return null;
	}

	private static IImportDeclaration getImportedType(ICompilationUnit cu, String typeName) throws CoreException {
		IImportDeclaration[] imports= cu.getImports();
		String dotTypeName= "." + typeName; //$NON-NLS-1$
		for (int i= 0; i < imports.length; i++){
			if (imports[i].getElementName().endsWith(dotTypeName))
				return imports[i];
		}
		return null;
	}

	private RefactoringStatus checkForMethodsWithConstructorNames()  throws CoreException{
		IMethod[] methods= fType.getMethods();
		for (int i= 0; i < methods.length; i++){
			if (methods[i].isConstructor())
				continue;
			RefactoringStatus check= Checks.checkIfConstructorName(methods[i], methods[i].getElementName(), getNewElementName());
			if (check != null)
				return check;
		}
		return null;
	}

	private RefactoringStatus checkImportedTypes() throws CoreException {
		RefactoringStatus result= new RefactoringStatus();
		IImportDeclaration[] imports= fType.getCompilationUnit().getImports();
		for (int i= 0; i < imports.length; i++)
			analyzeImportDeclaration(imports[i], result);
		return result;
	}

	private RefactoringStatus checkTypesInCompilationUnit() {
		RefactoringStatus result= new RefactoringStatus();
		if (! Checks.isTopLevel(fType)){ //the other case checked in checkTypesInPackage
			IType siblingType= fType.getDeclaringType().getType(getNewElementName());
			if (siblingType.exists()){
				String msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_member_type_exists,
					new String[] { getNewElementLabel(), BasicElementLabels.getJavaElementName(fType.getDeclaringType().getFullyQualifiedName('.'))});
				result.addError(msg, JavaStatusContext.create(siblingType));
			}
		}
		return result;
	}

	private RefactoringStatus analyseEnclosedTypes() throws CoreException {
		final ISourceRange typeRange= fType.getSourceRange();
		final RefactoringStatus result= new RefactoringStatus();
		CompilationUnit cuNode= new RefactoringASTParser(AST.JLS3).parse(fType.getCompilationUnit(), false);
		cuNode.accept(new ASTVisitor(){

			@Override
			public boolean visit(TypeDeclaration node){ // enums and annotations can't be local
				if (node.getStartPosition() <= typeRange.getOffset())
					return true;
				if (node.getStartPosition() > typeRange.getOffset() + typeRange.getLength())
					return true;

				if (getNewElementName().equals(node.getName().getIdentifier())){
					RefactoringStatusContext	context= JavaStatusContext.create(fType.getCompilationUnit(), node);
					String msg= null;
					if (node.isLocalTypeDeclaration()){
						msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_local_type,
									new String[]{JavaElementUtil.createSignature(fType), getNewElementLabel()});
					}
					else if (node.isMemberTypeDeclaration()){
						msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_member_type,
								new String[]{JavaElementUtil.createSignature(fType), getNewElementLabel()});
					}
					if (msg != null)
						result.addError(msg, context);
				}

				MethodDeclaration[] methods= node.getMethods();
				for (int i= 0; i < methods.length; i++) {
					if (Modifier.isNative(methods[i].getModifiers())){
						RefactoringStatusContext	context= JavaStatusContext.create(fType.getCompilationUnit(), methods[i]);
						String msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_enclosed_type_native, BasicElementLabels.getJavaElementName(node.getName().getIdentifier()));
						result.addWarning(msg, context);
					}
				}
				return true;
			}
		});
		return result;
	}

	private static ICompilationUnit getCompilationUnit(IImportDeclaration imp) {
		return (ICompilationUnit)imp.getParent().getParent();
	}

	private void analyzeImportedTypes(IType[] types, RefactoringStatus result, IImportDeclaration imp) throws CoreException {
		for (int i= 0; i < types.length; i++) {
			//could this be a problem (same package imports)?
			if (JdtFlags.isPublic(types[i]) && types[i].getElementName().equals(getNewElementName())){
				String msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_name_conflict1,
																			new Object[]{ JavaElementLabels.getElementLabel(types[i], JavaElementLabels.ALL_FULLY_QUALIFIED), BasicElementLabels.getPathLabel(getCompilationUnit(imp).getPath(), false)});
				result.addError(msg, JavaStatusContext.create(imp));
			}
		}
	}

	private static IJavaElement convertFromImportDeclaration(IImportDeclaration declaration) throws CoreException {
			if (declaration.isOnDemand()){
				String packageName= declaration.getElementName().substring(0, declaration.getElementName().length() - 2);
				return JavaModelUtil.findTypeContainer(declaration.getJavaProject(), packageName);
			} else
				return JavaModelUtil.findTypeContainer(declaration.getJavaProject(), declaration.getElementName());
	}

	private void analyzeImportDeclaration(IImportDeclaration imp, RefactoringStatus result) throws CoreException{
		if (!imp.isOnDemand())
			return; //analyzed earlier

		IJavaElement imported= convertFromImportDeclaration(imp);
		if (imported == null)
			return;

		if (imported instanceof IPackageFragment){
			ICompilationUnit[] cus= ((IPackageFragment)imported).getCompilationUnits();
			for (int i= 0; i < cus.length; i++) {
				analyzeImportedTypes(cus[i].getTypes(), result, imp);
			}
		} else {
			//cast safe: see JavaModelUtility.convertFromImportDeclaration
			analyzeImportedTypes(((IType)imported).getTypes(), result, imp);
		}
	}

	/*
	 * Analyzes all compilation units in which type is referenced
	 */
	private RefactoringStatus analyzeAffectedCompilationUnits(IProgressMonitor pm) throws CoreException {
		RefactoringStatus result= new RefactoringStatus();

		result.merge(Checks.checkCompileErrorsInAffectedFiles(fReferences, fType.getResource()));

		pm.beginTask("", fReferences.length); //$NON-NLS-1$
		result.merge(checkConflictingTypes(pm));
		return result;
	}

	private RefactoringStatus checkConflictingTypes(IProgressMonitor pm) throws CoreException {
		RefactoringStatus result= new RefactoringStatus();
		IJavaSearchScope scope= RefactoringScopeFactory.create(fType);
		SearchPattern pattern= SearchPattern.createPattern(getNewElementName(),
				IJavaSearchConstants.TYPE, IJavaSearchConstants.ALL_OCCURRENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
		ICompilationUnit[] cusWithReferencesToConflictingTypes= RefactoringSearchEngine.findAffectedCompilationUnits(pattern, scope, pm, result);
		if (cusWithReferencesToConflictingTypes.length == 0)
			return result;
		ICompilationUnit[] 	cusWithReferencesToRenamedType= getCus(fReferences);

		ICompilationUnit[] intersection= isIntersectionEmpty(cusWithReferencesToRenamedType, cusWithReferencesToConflictingTypes);
		if (intersection.length == 0)
			return result;

		for (int i= 0; i < intersection.length; i++) {
			RefactoringStatusContext context= JavaStatusContext.create(intersection[i]);
			String message= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_another_type,
				new String[] { getNewElementLabel(), BasicElementLabels.getFileName(intersection[i])});
			result.addError(message, context);
		}
		return result;
	}

	private static ICompilationUnit[] isIntersectionEmpty(ICompilationUnit[] a1, ICompilationUnit[] a2){
		Set<ICompilationUnit> set1= new HashSet<ICompilationUnit>(Arrays.asList(a1));
		Set<ICompilationUnit> set2= new HashSet<ICompilationUnit>(Arrays.asList(a2));
		set1.retainAll(set2);
		return set1.toArray(new ICompilationUnit[set1.size()]);
	}

	private static ICompilationUnit[] getCus(SearchResultGroup[] searchResultGroups){
		List<ICompilationUnit> cus= new ArrayList<ICompilationUnit>(searchResultGroups.length);
		for (int i= 0; i < searchResultGroups.length; i++) {
			ICompilationUnit cu= searchResultGroups[i].getCompilationUnit();
			if (cu != null)
				cus.add(cu);
		}
		return cus.toArray(new ICompilationUnit[cus.size()]);
	}

	@Override
	public Change createChange(IProgressMonitor monitor) throws CoreException {
		try {
			monitor.beginTask(RefactoringCoreMessages.RenameTypeRefactoring_creating_change, 4);
			String project= null;
			IJavaProject javaProject= fType.getJavaProject();
			if (javaProject != null)
				project= javaProject.getElementName();
			int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE;
			try {
				if (!Flags.isPrivate(fType.getFlags()))
					flags|= RefactoringDescriptor.MULTI_CHANGE;
				if (fType.isAnonymous() || fType.isLocal())
					flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
			} catch (JavaModelException exception) {
				JavaPlugin.log(exception);
			}
			final String description= Messages.format(RefactoringCoreMessages.RenameTypeProcessor_descriptor_description_short, BasicElementLabels.getJavaElementName(fType.getElementName()));
			final String header= Messages.format(RefactoringCoreMessages.RenameTypeProcessor_descriptor_description, new String[] { JavaElementLabels.getElementLabel(fType, JavaElementLabels.ALL_FULLY_QUALIFIED), getNewElementLabel()});
			final String comment= new JDTRefactoringDescriptorComment(project, this, header).asString();
			final RenameJavaElementDescriptor descriptor= RefactoringSignatureDescriptorFactory.createRenameJavaElementDescriptor(IJavaRefactorings.RENAME_TYPE);
			descriptor.setProject(project);
			descriptor.setDescription(description);
			descriptor.setComment(comment);
			descriptor.setFlags(flags);
			descriptor.setJavaElement(fType);
			descriptor.setNewName(getNewElementName());
			descriptor.setUpdateQualifiedNames(fUpdateQualifiedNames);
			descriptor.setUpdateTextualOccurrences(fUpdateTextualMatches);
			descriptor.setUpdateReferences(fUpdateReferences);
			if (fUpdateQualifiedNames && fFilePatterns != null && !"".equals(fFilePatterns)) //$NON-NLS-1$
				descriptor.setFileNamePatterns(fFilePatterns);
			descriptor.setUpdateSimilarDeclarations(fUpdateSimilarElements);
			descriptor.setMatchStrategy(fRenamingStrategy);
			final DynamicValidationRefactoringChange result= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.RenameTypeProcessor_change_name);

			if (fChangeManager.containsChangesIn(fType.getCompilationUnit())) {
				TextChange textChange= fChangeManager.get(fType.getCompilationUnit());
				if (textChange instanceof TextFileChange) {
					((TextFileChange) textChange).setSaveMode(TextFileChange.FORCE_SAVE);
				}
			}
			result.addAll(fChangeManager.getAllChanges());
			if (willRenameCU()) {
				IResource resource= fType.getCompilationUnit().getResource();
				if (resource != null && resource.isLinked()) {
					String ext= resource.getFileExtension();
					String renamedResourceName;
					if (ext == null)
						renamedResourceName= getNewElementName();
					else
						renamedResourceName= getNewElementName() + '.' + ext;
					result.add(new RenameResourceChange(fType.getCompilationUnit().getPath(), renamedResourceName));
				} else {
					String renamedCUName= JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), getNewElementName());
					result.add(new RenameCompilationUnitChange(fType.getCompilationUnit(), renamedCUName));
				}
			}
			monitor.worked(1);
			return result;
		} finally {
			fChangeManager= null;
		}
	}

	@Override
	public Change postCreateChange(Change[] participantChanges, IProgressMonitor pm) throws CoreException {
		if (fQualifiedNameSearchResult != null) {
			try {
				return fQualifiedNameSearchResult.getSingleChange(Changes.getModifiedFiles(participantChanges));
			} finally {
				fQualifiedNameSearchResult= null;
			}
		} else {
			return null;
		}
	}

	private boolean willRenameCU() {
		String name = JavaCore.removeJavaLikeExtension(fType.getCompilationUnit().getElementName());
		if (! (Checks.isTopLevel(fType) && name.equals(fType.getElementName())))
			return false;
		if (! checkNewPathValidity().isOK())
			return false;
		if (! Checks.checkCompilationUnitNewName(fType.getCompilationUnit(), getNewElementName()).isOK())
			return false;
		return true;
	}

	private void createChanges(IProgressMonitor pm) throws CoreException {
		try{
			pm.beginTask("", 12); //$NON-NLS-1$
			pm.setTaskName(RefactoringCoreMessages.RenameTypeProcessor_creating_changes);

			if (fUpdateReferences)
				addReferenceUpdates(fChangeManager, new SubProgressMonitor(pm, 3));

			// Similar names updates have already been added.

			pm.worked(1);

			IResource resource= fType.getCompilationUnit().getResource();
			// if we have a linked resource then we don't use CU renaming
			// directly. So we have to update the code by ourselves.
			if ((resource != null && resource.isLinked()) || !willRenameCU()) {
				addTypeDeclarationUpdate(fChangeManager);
				pm.worked(1);

				addConstructorRenames(fChangeManager);
				pm.worked(1);
			} else {
				pm.worked(2);
			}

			if (fUpdateTextualMatches) {
				pm.subTask(RefactoringCoreMessages.RenameTypeRefactoring_searching_text);
				TextMatchUpdater.perform(new SubProgressMonitor(pm, 1), RefactoringScopeFactory.create(fType), this, fChangeManager, fReferences);
				if (fUpdateSimilarElements)
					addSimilarElementsTextualUpdates(fChangeManager, new SubProgressMonitor(pm, 3));
			}

		} finally{
			pm.done();
		}
	}

	private void addTypeDeclarationUpdate(TextChangeManager manager) throws CoreException {
		String name= RefactoringCoreMessages.RenameTypeRefactoring_update;
		int typeNameLength= fType.getElementName().length();
		ICompilationUnit cu= fType.getCompilationUnit();
		TextChangeCompatibility.addTextEdit(manager.get(cu), name, new ReplaceEdit(fType.getNameRange().getOffset(), typeNameLength, getNewElementName()));
	}

	private void addConstructorRenames(TextChangeManager manager) throws CoreException {
		ICompilationUnit cu= fType.getCompilationUnit();
		IMethod[] methods= fType.getMethods();
		int typeNameLength= fType.getElementName().length();
		for (int i= 0; i < methods.length; i++){
			if (methods[i].isConstructor()) {
				/*
				 * constructor declarations cannot be fully qualified so we can use simple replace here
				 *
				 * if (methods[i].getNameRange() == null), then it's a binary file so it's wrong anyway
				 * (checked as a precondition)
				 */
				String name= RefactoringCoreMessages.RenameTypeRefactoring_rename_constructor;
				TextChangeCompatibility.addTextEdit(manager.get(cu), name, new ReplaceEdit(methods[i].getNameRange().getOffset(), typeNameLength, getNewElementName()));
			}
		}
	}

	private void addReferenceUpdates(TextChangeManager manager, IProgressMonitor pm) {
		pm.beginTask("", fReferences.length); //$NON-NLS-1$
		for (int i= 0; i < fReferences.length; i++){
			ICompilationUnit cu= fReferences[i].getCompilationUnit();
			if (cu == null)
				continue;

			String name= RefactoringCoreMessages.RenameTypeRefactoring_update_reference;
			SearchMatch[] results= fReferences[i].getSearchResults();

			for (int j= 0; j < results.length; j++){
				SearchMatch match= results[j];
				ReplaceEdit replaceEdit= new ReplaceEdit(match.getOffset(), match.getLength(), getNewElementName());
				TextChangeCompatibility.addTextEdit(manager.get(cu), name, replaceEdit, CATEGORY_TYPE_RENAME);
			}
			pm.worked(1);
		}
	}

	private void computeQualifiedNameMatches(IProgressMonitor pm) {
		IPackageFragment fragment= fType.getPackageFragment();
		if (fQualifiedNameSearchResult == null)
			fQualifiedNameSearchResult= new QualifiedNameSearchResult();
		QualifiedNameFinder.process(fQualifiedNameSearchResult, fType.getFullyQualifiedName(),
			fragment.getElementName() + "." + getNewElementName(), //$NON-NLS-1$
			fFilePatterns, fType.getJavaProject().getProject(), pm);
	}

	private RefactoringStatus initialize(JavaRefactoringArguments extended) {
		final String handle= extended.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
		if (handle != null) {
			final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(extended.getProject(), handle, false);
			if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE)
				return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getProcessorName(), IJavaRefactorings.RENAME_TYPE);
			else
				fType= (IType) element;
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
		final String name= extended.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME);
		if (name != null && !"".equals(name)) //$NON-NLS-1$
			setNewElementName(name);
		else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME));
		final String patterns= extended.getAttribute(ATTRIBUTE_PATTERNS);
		if (patterns != null && !"".equals(patterns)) //$NON-NLS-1$
			fFilePatterns= patterns;
		final String references= extended.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_REFERENCES);
		if (references != null) {
			fUpdateReferences= Boolean.valueOf(references).booleanValue();
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_REFERENCES));
		final String matches= extended.getAttribute(ATTRIBUTE_TEXTUAL_MATCHES);
		if (matches != null) {
			fUpdateTextualMatches= Boolean.valueOf(matches).booleanValue();
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_TEXTUAL_MATCHES));
		final String qualified= extended.getAttribute(ATTRIBUTE_QUALIFIED);
		if (qualified != null) {
			fUpdateQualifiedNames= Boolean.valueOf(qualified).booleanValue();
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_QUALIFIED));
		final String similarDeclarations= extended.getAttribute(ATTRIBUTE_SIMILAR_DECLARATIONS);
		if (similarDeclarations != null)
			fUpdateSimilarElements= Boolean.valueOf(similarDeclarations).booleanValue();
		else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_SIMILAR_DECLARATIONS));
		final String similarDeclarationsMatchingStrategy= extended.getAttribute(ATTRIBUTE_MATCHING_STRATEGY);
		if (similarDeclarationsMatchingStrategy != null) {
			try {
				fRenamingStrategy= Integer.valueOf(similarDeclarationsMatchingStrategy).intValue();
			} catch (NumberFormatException e) {
				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new String[] { similarDeclarationsMatchingStrategy,
						ATTRIBUTE_QUALIFIED }));
			}
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_MATCHING_STRATEGY));
		return new RefactoringStatus();
	}

	// --------- Similar names

	/**
	 * Creates and initializes the refactoring processors for similarly named elements
	 * @param progressMonitor progress monitor
	 * @param context context
	 * @return status
	 * @throws CoreException should not happen
	 */
	private RefactoringStatus initializeSimilarElementsRenameProcessors(IProgressMonitor progressMonitor, CheckConditionsContext context) throws CoreException {

		Assert.isNotNull(fPreloadedElementToName);
		Assert.isNotNull(fPreloadedElementToSelection);

		final RefactoringStatus status= new RefactoringStatus();
		final Set<IMethod> handledTopLevelMethods= new HashSet<IMethod>();
		final Set<Warning> warnings= new HashSet<Warning>();
		final List<RefactoringProcessor> processors= new ArrayList<RefactoringProcessor>();
		fFinalSimilarElementToName= new HashMap<IJavaElement, String>();

		CompilationUnit currentResolvedCU= null;
		ICompilationUnit currentCU= null;

		int current= 0;
		final int max= fPreloadedElementToName.size();

		progressMonitor.beginTask("", max * 3); //$NON-NLS-1$
		progressMonitor.setTaskName(RefactoringCoreMessages.RenameTypeProcessor_checking_similarly_named_declarations_refactoring_conditions);

		for (Iterator<IJavaElement> iter= fPreloadedElementToName.keySet().iterator(); iter.hasNext();) {

			final IJavaElement element= iter.next();

			current++;
			progressMonitor.worked(3);

			// not selected? -> skip
			if (! (fPreloadedElementToSelection.get(element)).booleanValue())
				continue;

			// already registered? (may happen with overridden methods) -> skip
			if (fFinalSimilarElementToName.containsKey(element))
				continue;

			// CompilationUnit changed? (note: fPreloadedElementToName is sorted by CompilationUnit)
			ICompilationUnit newCU= (ICompilationUnit) element.getAncestor(IJavaElement.COMPILATION_UNIT);

			if (!newCU.equals(currentCU)) {

				checkCUCompleteConditions(status, currentResolvedCU, currentCU, processors);

				if (status.hasFatalError())
					return status;

				// reset values
				currentResolvedCU= null;
				currentCU= newCU;
				processors.clear();
			}

			final String newName= fPreloadedElementToName.get(element);
			RefactoringProcessor processor= null;

			if (element instanceof ILocalVariable) {
				final ILocalVariable currentLocal= (ILocalVariable) element;

				if (currentResolvedCU == null)
					currentResolvedCU= new RefactoringASTParser(AST.JLS3).parse(currentCU, true);

				processor= createLocalRenameProcessor(currentLocal, newName, currentResolvedCU);

				// don't check for conflicting rename => is done by #checkCUCompleteConditions().

				if (status.hasFatalError())
					return status;
				fFinalSimilarElementToName.put(currentLocal, newName);
			}
			if (element instanceof IField) {
				final IField currentField= (IField) element;
				processor= createFieldRenameProcessor(currentField, newName);

				status.merge(checkForConflictingRename(currentField, newName));
				if (status.hasFatalError())
					return status;
				fFinalSimilarElementToName.put(currentField, newName);
			}
			if (element instanceof IMethod) {
				IMethod currentMethod= (IMethod) element;
				if (MethodChecks.isVirtual(currentMethod)) {

					final IType declaringType= currentMethod.getDeclaringType();
					ITypeHierarchy hierarchy= null;
					if (!declaringType.isInterface())
						hierarchy= declaringType.newTypeHierarchy(new NullProgressMonitor());

					final IMethod topmost= MethodChecks.getTopmostMethod(currentMethod, hierarchy, new NullProgressMonitor());
					if (topmost != null)
						currentMethod= topmost;
					if (handledTopLevelMethods.contains(currentMethod))
						continue;
					handledTopLevelMethods.add(currentMethod);
					final IMethod[] ripples= RippleMethodFinder2.getRelatedMethods(currentMethod, new NullProgressMonitor(), null);

					if (checkForWarnings(warnings, newName, ripples))
						continue;

					status.merge(checkForConflictingRename(ripples, newName));
					if (status.hasFatalError())
						return status;

					processor= createVirtualMethodRenameProcessor(currentMethod, newName, ripples, hierarchy);
					fFinalSimilarElementToName.put(currentMethod, newName);
					for (int i= 0; i < ripples.length; i++) {
						fFinalSimilarElementToName.put(ripples[i], newName);
					}
				} else {

					status.merge(checkForConflictingRename(new IMethod[] { currentMethod }, newName));
					if (status.hasFatalError())
						break;

					fFinalSimilarElementToName.put(currentMethod, newName);

					processor= createNonVirtualMethodRenameProcessor(currentMethod, newName);
				}
			}

			progressMonitor.subTask(Messages.format(RefactoringCoreMessages.RenameTypeProcessor_progress_current_total, new Object[] { String.valueOf(current), String.valueOf(max)}));

			status.merge(processor.checkInitialConditions(new NoOverrideProgressMonitor(progressMonitor, 1)));

			if (status.hasFatalError())
				return status;

			status.merge(processor.checkFinalConditions(new NoOverrideProgressMonitor(progressMonitor, 1), context));

			if (status.hasFatalError())
				return status;

			processors.add(processor);

			progressMonitor.worked(1);

			if (progressMonitor.isCanceled())
				throw new OperationCanceledException();
		}

		// check last CU
		checkCUCompleteConditions(status, currentResolvedCU, currentCU, processors);

		status.merge(addWarnings(warnings));

		progressMonitor.done();
		return status;
	}

	private void checkCUCompleteConditions(final RefactoringStatus status, CompilationUnit currentResolvedCU, ICompilationUnit currentCU, List<RefactoringProcessor> processors) throws CoreException {

		// check local variable conditions
		List<RefactoringProcessor> locals= getProcessorsOfType(processors, RenameLocalVariableProcessor.class);
		if (!locals.isEmpty()) {
			RenameAnalyzeUtil.LocalAnalyzePackage[] analyzePackages= new RenameAnalyzeUtil.LocalAnalyzePackage[locals.size()];
			TextChangeManager manager= new TextChangeManager();
			int current= 0;
			TextChange textChange= manager.get(currentCU);
			textChange.setKeepPreviewEdits(true);
			for (Iterator<RefactoringProcessor> iterator= locals.iterator(); iterator.hasNext();) {
				RenameLocalVariableProcessor localProcessor= (RenameLocalVariableProcessor) iterator.next();
				RenameAnalyzeUtil.LocalAnalyzePackage analyzePackage= localProcessor.getLocalAnalyzePackage();
				analyzePackages[current]= analyzePackage;
				for (int i= 0; i < analyzePackage.fOccurenceEdits.length; i++) {
					TextChangeCompatibility.addTextEdit(textChange, "", analyzePackage.fOccurenceEdits[i], GroupCategorySet.NONE); //$NON-NLS-1$
				}
				current++;
			}
			status.merge(RenameAnalyzeUtil.analyzeLocalRenames(analyzePackages, textChange, currentResolvedCU, false));
		}

		/*
		 * There is room for performance improvement here: One could move
		 * shadowing analyzes out of the field and method processors and perform
		 * it here, thus saving on working copy creation. Drawback is increased
		 * heap consumption.
		 */
	}

	private List<RefactoringProcessor> getProcessorsOfType(List<RefactoringProcessor> processors, Class<RenameLocalVariableProcessor> type) {
		List<RefactoringProcessor> tmp= new ArrayList<RefactoringProcessor>();
		for (Iterator<RefactoringProcessor> iter= processors.iterator(); iter.hasNext();) {
			RefactoringProcessor element= iter.next();
			if (element.getClass().equals(type))
				tmp.add(element);
		}
		return tmp;
	}

	// ------------------ Error checking -------------

	/**
	 * Checks whether one of the given methods, which will all be renamed to
	 * "newName", shares a type with another already registered method which is
	 * renamed to the same new name and shares the same parameters.
	 * @param methods methods to check
	 * @param newName the new name
	 * @return status
	 *
	 * @see #checkForConflictingRename(IField, String)
	 */
	private RefactoringStatus checkForConflictingRename(IMethod[] methods, String newName) {
		RefactoringStatus status= new RefactoringStatus();
		for (Iterator<IJavaElement> iter= fFinalSimilarElementToName.keySet().iterator(); iter.hasNext();) {
			IJavaElement element= iter.next();
			if (element instanceof IMethod) {
				IMethod alreadyRegisteredMethod= (IMethod) element;
				String alreadyRegisteredMethodName= fFinalSimilarElementToName.get(element);
				for (int i= 0; i < methods.length; i++) {
					IMethod method2= methods[i];
					if ( (alreadyRegisteredMethodName.equals(newName)) && (method2.getDeclaringType().equals(alreadyRegisteredMethod.getDeclaringType()))
							&& (sameParams(alreadyRegisteredMethod, method2))) {
						String message= Messages.format(RefactoringCoreMessages.RenameTypeProcessor_cannot_rename_methods_same_new_name,
								new String[] { BasicElementLabels.getJavaElementName(alreadyRegisteredMethod.getElementName()),
								BasicElementLabels.getJavaElementName(method2.getElementName()),
								BasicElementLabels.getJavaElementName(alreadyRegisteredMethod.getDeclaringType().getFullyQualifiedName('.')), BasicElementLabels.getJavaElementName(newName) });
						status.addFatalError(message);
						return status;
					}
				}
			}
		}
		return status;
	}

	private static boolean sameParams(IMethod method, IMethod method2) {

		if (method.getNumberOfParameters() != method2.getNumberOfParameters())
			return false;

		String[] params= method.getParameterTypes();
		String[] params2= method2.getParameterTypes();

		for (int i= 0; i < params.length; i++) {
			String t1= Signature.getSimpleName(Signature.toString(params[i]));
			String t2= Signature.getSimpleName(Signature.toString(params2[i]));
			if (!t1.equals(t2)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * If suffix matching is enabled, the refactoring may suggest two fields to
	 * have the same name which reside in the same type. Same thing may also
	 * happen if the user makes poor choices for the field names.
	 *
	 * Consider: FooBarThing fFooBarThing; FooBarThing fBarThing;
	 *
	 * Rename "FooBarThing" to "DifferentHunk". Suggestion for both fields is
	 * "fDifferentHunk" (and rightly so).
	 * @param currentField field
	 * @param newName new name
	 * @return status
	 */
	private RefactoringStatus checkForConflictingRename(IField currentField, String newName) {
		RefactoringStatus status= new RefactoringStatus();
		for (Iterator<IJavaElement> iter= fFinalSimilarElementToName.keySet().iterator(); iter.hasNext();) {
			IJavaElement element= iter.next();
			if (element instanceof IField) {
				IField alreadyRegisteredField= (IField) element;
				String alreadyRegisteredFieldName= fFinalSimilarElementToName.get(element);
				if (alreadyRegisteredFieldName.equals(newName)) {
					if (alreadyRegisteredField.getDeclaringType().equals(currentField.getDeclaringType())) {

						String message= Messages.format(RefactoringCoreMessages.RenameTypeProcessor_cannot_rename_fields_same_new_name,
								new String[] { BasicElementLabels.getJavaElementName(alreadyRegisteredField.getElementName()),
								BasicElementLabels.getJavaElementName(currentField.getElementName()),
								BasicElementLabels.getJavaElementName(alreadyRegisteredField.getDeclaringType().getFullyQualifiedName('.')), BasicElementLabels.getJavaElementName(newName) });
						status.addFatalError(message);
						return status;
					}
				}
			}
		}
		return status;
	}

	private RefactoringStatus addWarnings(final Set<Warning> warnings) {
		RefactoringStatus status= new RefactoringStatus();

		// Remove deleted ripple methods from user selection and add warnings
		for (Iterator<Warning> iter= warnings.iterator(); iter.hasNext();) {
			final Warning warning= iter.next();
			final IMethod[] elements= warning.getRipple();
			if (warning.isSelectionWarning()) {
				String message= Messages.format(RefactoringCoreMessages.RenameTypeProcessor_deselected_method_is_overridden,
						new String[] { JavaElementLabels.getElementLabel(elements[0], JavaElementLabels.ALL_DEFAULT),
								JavaElementLabels.getElementLabel(elements[0].getDeclaringType(), JavaElementLabels.ALL_DEFAULT) });
				status.addWarning(message);
			}
			if (warning.isNameWarning()) {
				String message= Messages.format(
						RefactoringCoreMessages.RenameTypeProcessor_renamed_method_is_overridden, new String[] {
								JavaElementLabels.getElementLabel(elements[0], JavaElementLabels.ALL_DEFAULT),
								JavaElementLabels.getElementLabel(elements[0].getDeclaringType(), JavaElementLabels.ALL_DEFAULT) });
				status.addWarning(message);
			}
			for (int i= 0; i < elements.length; i++)
				fPreloadedElementToSelection.put(elements[i], Boolean.FALSE);
		}
		return status;
	}

	/*
	 * If one of the methods of this ripple was deselected or renamed by
	 * the user, deselect the whole chain and add warnings.
	 */
	private boolean checkForWarnings(final Set<Warning> warnings, final String newName, final IMethod[] ripples) {

		boolean addSelectionWarning= false;
		boolean addNameWarning= false;
		for (int i= 0; i < ripples.length; i++) {
			String newNameOfRipple= fPreloadedElementToName.get(ripples[i]);
			Boolean selected= fPreloadedElementToSelection.get(ripples[i]);

			// selected may be null here due to supermethods like
			// setSomeClass(Object class) (subsignature match)
			// Don't add a warning.
			if (selected == null)
				continue;

			if (!selected.booleanValue())
				addSelectionWarning= true;

			if (!newName.equals(newNameOfRipple))
				addNameWarning= true;
		}
		if (addSelectionWarning || addNameWarning)
			warnings.add(new Warning(ripples, addSelectionWarning, addNameWarning));

		return (addSelectionWarning || addNameWarning);
	}

	private class Warning {

		private IMethod[] fRipple;
		private boolean fSelectionWarning;
		private boolean fNameWarning;

		public Warning(IMethod[] ripple, boolean isSelectionWarning, boolean isNameWarning) {
			fRipple= ripple;
			fSelectionWarning= isSelectionWarning;
			fNameWarning= isNameWarning;
		}

		public boolean isNameWarning() {
			return fNameWarning;
		}

		public IMethod[] getRipple() {
			return fRipple;
		}

		public boolean isSelectionWarning() {
			return fSelectionWarning;
		}
	}

	// ----------------- Processor creation --------

	private RenameMethodProcessor createVirtualMethodRenameProcessor(IMethod currentMethod, String newMethodName, IMethod[] ripples, ITypeHierarchy hierarchy) {
		RenameMethodProcessor processor= new RenameVirtualMethodProcessor(currentMethod, ripples, fChangeManager, hierarchy, CATEGORY_METHOD_RENAME);
		initMethodProcessor(processor, newMethodName);
		return processor;
	}

	private RenameMethodProcessor createNonVirtualMethodRenameProcessor(IMethod currentMethod, String newMethodName) {
		RenameMethodProcessor processor= new RenameNonVirtualMethodProcessor(currentMethod, fChangeManager, CATEGORY_METHOD_RENAME);
		initMethodProcessor(processor, newMethodName);
		return processor;
	}

	private void initMethodProcessor(RenameMethodProcessor processor, String newMethodName) {
		processor.setNewElementName(newMethodName);
		processor.setUpdateReferences(getUpdateReferences());
	}

	private RenameFieldProcessor createFieldRenameProcessor(final IField field, final String newName) {
		final RenameFieldProcessor processor= new RenameFieldProcessor(field, fChangeManager, CATEGORY_FIELD_RENAME);
		processor.setNewElementName(newName);
		processor.setRenameGetter(false);
		processor.setRenameSetter(false);
		processor.setUpdateReferences(getUpdateReferences());
		processor.setUpdateTextualMatches(false);
		return processor;
	}

	private RenameLocalVariableProcessor createLocalRenameProcessor(final ILocalVariable local, final String newName, final CompilationUnit compilationUnit) {
		final RenameLocalVariableProcessor processor= new RenameLocalVariableProcessor(local, fChangeManager, compilationUnit, CATEGORY_LOCAL_RENAME);
		processor.setNewElementName(newName);
		processor.setUpdateReferences(getUpdateReferences());
		return processor;
	}

	// ----------- Edit creation -----------


	/**
	 * Updates textual matches for fields.
	 *
	 * Strategy for matching text matches: Match and replace all fully qualified
	 * field names, but non-qualified field names only iff there are no fields
	 * which have the same original, but a different new name. Don't add java
	 * references; duplicate edits may be created but do not matter.
	 * @param manager text change manager
	 * @param monitor progress monitor
	 * @throws CoreException if updating failed
	 */
	private void addSimilarElementsTextualUpdates(TextChangeManager manager, IProgressMonitor monitor) throws CoreException {

		final Map<String, String> simpleNames= new HashMap<String, String>();
		final List<String> forbiddenSimpleNames= new ArrayList<String>();

		for (Iterator<IJavaElement> iter= fFinalSimilarElementToName.keySet().iterator(); iter.hasNext();) {
			final IJavaElement element= iter.next();
			if (element instanceof IField) {

				if (forbiddenSimpleNames.contains(element.getElementName()))
					continue;

				final String registeredNewName= simpleNames.get(element.getElementName());
				final String newNameToCheck= fFinalSimilarElementToName.get(element);
				if (registeredNewName == null)
					simpleNames.put(element.getElementName(), newNameToCheck);
				else if (!registeredNewName.equals(newNameToCheck))
					forbiddenSimpleNames.add(element.getElementName());
			}
		}

		for (Iterator<IJavaElement> iter= fFinalSimilarElementToName.keySet().iterator(); iter.hasNext();) {
			final IJavaElement element= iter.next();
			if (element instanceof IField) {
				final IField field= (IField) element;
				final String newName= fFinalSimilarElementToName.get(field);
				TextMatchUpdater.perform(monitor, RefactoringScopeFactory.create(field), field.getElementName(), field.getDeclaringType().getFullyQualifiedName(), newName, manager,
						new SearchResultGroup[0], forbiddenSimpleNames.contains(field.getElementName()));
			}
		}
	}

	// ------ UI interaction

	/**
	 * @return the map of similarly named elements (IJavaElement -> String with new name)
	 * This map is live. Callers may change the new names of the elements; they
	 * may not change the key set.
	 */
	public Map<IJavaElement, String> getSimilarElementsToNewNames() {
		return fPreloadedElementToName;
	}

	/**
	 * @return the map of similarly named elements (IJavaElement -> Boolean if selected) This
	 * map is live. Callers may change the selection status of the elements;
	 * they may not change the key set.
	 */
	public Map<IJavaElement, Boolean> getSimilarElementsToSelection() {
		return fPreloadedElementToSelection;
	}

	/**
	 * Resets the element maps back to the original status. This affects the
	 * maps returned in {@link #getSimilarElementsToNewNames() } and
	 * {@link #getSimilarElementsToSelection() }. All new names are reset to
	 * the calculated ones and every element gets selected.
	 */
	public void resetSelectedSimilarElements() {
		Assert.isNotNull(fPreloadedElementToName);
		for (Iterator<IJavaElement> iter= fPreloadedElementToNameDefault.keySet().iterator(); iter.hasNext();) {
			final IJavaElement element= iter.next();
			fPreloadedElementToName.put(element, fPreloadedElementToNameDefault.get(element));
			fPreloadedElementToSelection.put(element, Boolean.TRUE);
		}
	}

	/**
	 * @return true iff the "update similarly named elements" flag is set AND the
	 * search yielded some elements to be renamed.
	 */
	public boolean hasSimilarElementsToRename() {
		if (!fUpdateSimilarElements)
			return false;
		if (fPreloadedElementToName == null)
			return false;
		if (fPreloadedElementToName.size() == 0)
			return false;
		return true;
	}
}
