/*******************************************************************************
 * Copyright (c) 2000, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.corext.refactoring.rename;

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

import org.eclipse.text.edits.ReplaceEdit;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubProgressMonitor;

import org.eclipse.core.resources.IFile;

import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.GroupCategorySet;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.TextChange;
import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
import org.eclipse.ltk.core.refactoring.participants.RenameArguments;

import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaConventions;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.MethodDeclarationMatch;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchParticipant;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.SearchRequestor;

import org.eclipse.jdt.internal.corext.refactoring.Checks;
import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptor;
import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorComment;
import org.eclipse.jdt.internal.corext.refactoring.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.changes.DynamicValidationRefactoringChange;
import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility;
import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateCreator;
import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateMethodCreator;
import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors;
import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
import org.eclipse.jdt.internal.corext.refactoring.tagging.IDelegateUpdating;
import org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating;
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.internal.ui.JavaPlugin;

public abstract class RenameMethodProcessor extends JavaRenameProcessor implements IReferenceUpdating, IDelegateUpdating {

	public static final String ID_RENAME_METHOD= "org.eclipse.jdt.ui.rename.method"; //$NON-NLS-1$
	private static final String ATTRIBUTE_REFERENCES= "references"; //$NON-NLS-1$
	private static final String ATTRIBUTE_DELEGATE= "delegate"; //$NON-NLS-1$
	private static final String ATTRIBUTE_DEPRECATE= "deprecate"; //$NON-NLS-1$

	private SearchResultGroup[] fOccurrences;
	private boolean fUpdateReferences;
	private IMethod fMethod;
	private Set/*<IMethod>*/ fMethodsToRename;
	private TextChangeManager fChangeManager;
	private WorkingCopyOwner fWorkingCopyOwner;
	private boolean fIsComposite;
	private GroupCategorySet fCategorySet;
	private boolean fDelegateUpdating;
	private boolean fDelegateDeprecation;
	protected boolean fInitialized= false;

	public static final String IDENTIFIER= "org.eclipse.jdt.ui.renameMethodProcessor"; //$NON-NLS-1$
	
	/**
	 * Creates a new rename method processor.
	 * @param method the method, or <code>null</code> if invoked by scripting
	 */
	protected RenameMethodProcessor(IMethod method) {
		this(method, new TextChangeManager(true), null);
		fIsComposite= false;
	}
	
	/**
	 * Creates a new rename method processor.
	 * <p>
	 * This constructor is only invoked by <code>RenameTypeProcessor</code>.
	 * </p>
	 * 
	 * @param method the method
	 * @param manager the change manager
	 * @param categorySet the group category set
	 */
	protected RenameMethodProcessor(IMethod method, TextChangeManager manager, GroupCategorySet categorySet) {
		initialize(method);
		fChangeManager= manager;
		fCategorySet= categorySet;
		fDelegateUpdating= false;
		fDelegateDeprecation= true;
		fIsComposite= true;
	}
	
	protected void initialize(IMethod method) {
		fMethod= method;
		if (!fInitialized) {
			if (method != null)
				setNewElementName(method.getElementName());
			fUpdateReferences= true;
			initializeWorkingCopyOwner();
		}		
	}

	protected void initializeWorkingCopyOwner() {
		fWorkingCopyOwner= new WorkingCopyOwner() {/*must subclass*/};
	}
	
	protected void setData(RenameMethodProcessor other) {
		fUpdateReferences= other.fUpdateReferences;
		setNewElementName(other.getNewElementName());
	}

	public String getIdentifier() {
		return IDENTIFIER;
	}

	public boolean isApplicable() throws CoreException {
		return RefactoringAvailabilityTester.isRenameAvailable(fMethod);
	}

	public String getProcessorName() {
		return RefactoringCoreMessages.RenameMethodRefactoring_name;
	}
	
	protected String[] getAffectedProjectNatures() throws CoreException {
		return JavaProcessors.computeAffectedNatures(fMethod);
	}

	public Object[] getElements() {
		return new Object[] {fMethod};
	}

	protected RenameModifications computeRenameModifications() throws CoreException {
		RenameModifications result= new RenameModifications();
		RenameArguments args= new RenameArguments(getNewElementName(), getUpdateReferences());
		for (Iterator iter= fMethodsToRename.iterator(); iter.hasNext();) {
			IMethod method= (IMethod) iter.next();
			result.rename(method, args);
		}
		return result;
	}
	
	protected IFile[] getChangedFiles() throws CoreException {
		return ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits());
	}
	
	//---- IRenameProcessor -------------------------------------
	
	public final String getCurrentElementName(){
		return fMethod.getElementName();
	}
		
	public final RefactoringStatus checkNewElementName(String newName) {
		Assert.isNotNull(newName, "new name"); //$NON-NLS-1$
				
		RefactoringStatus status= Checks.checkName(newName, JavaConventions.validateMethodName(newName));
		if (status.isOK() && Checks.startsWithUpperCase(newName))
			status= RefactoringStatus.createWarningStatus(fIsComposite 
					? Messages.format(RefactoringCoreMessages.Checks_method_names_lowercase2, new String[] { newName, fMethod.getDeclaringType().getElementName()})
					: RefactoringCoreMessages.Checks_method_names_lowercase);
		
		if (Checks.isAlreadyNamed(fMethod, newName))
			status.addFatalError(fIsComposite 
					? Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_same_name2, new String[] { newName, fMethod.getDeclaringType().getElementName() } ) 
					: RefactoringCoreMessages.RenameMethodRefactoring_same_name,
					JavaStatusContext.create(fMethod)); 
		return status;
	}
	
	public Object getNewElement() {
		return fMethod.getDeclaringType().getMethod(getNewElementName(), fMethod.getParameterTypes());
	}
	
	public final IMethod getMethod() {
		return fMethod;
	}
	
	private void initializeMethodsToRename(IProgressMonitor pm) throws CoreException {
		if (fMethodsToRename == null)
			fMethodsToRename= new HashSet(Arrays.asList(MethodChecks.getOverriddenMethods(getMethod(), pm)));
	}
	
	protected void setMethodsToRename(IMethod[] methods) {
		fMethodsToRename= new HashSet(Arrays.asList(methods));
	}
	
	protected Set getMethodsToRename() {
		return fMethodsToRename;
	}
	
	//---- IReferenceUpdating -----------------------------------

	public boolean canEnableUpdateReferences() {
		return true;
	}

	public final void setUpdateReferences(boolean update) {
		fUpdateReferences= update;
	}	
	
	public boolean getUpdateReferences() {
		return fUpdateReferences;
	}	
	
	//------------------- IDelegateUpdating ----------------------
		
	public boolean canEnableDelegateUpdating() {
		return true;
	}

	public boolean getDelegateUpdating() {
		return fDelegateUpdating;
	}

	public void setDelegateUpdating(boolean updating) {
		fDelegateUpdating= updating;
	}

	public boolean getDeprecateDelegates() {
		return fDelegateDeprecation;
	}

	public void setDeprecateDelegates(boolean deprecate) {
		fDelegateDeprecation= deprecate;
	}

	//----------- preconditions ------------------

	public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
		if (fMethod == null || ! fMethod.exists()){
			String message= Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_deleted, 
								fMethod.getCompilationUnit().getElementName());
			return RefactoringStatus.createFatalErrorStatus(message);
		}	
		
		RefactoringStatus result= Checks.checkAvailability(fMethod);
		if (result.hasFatalError())
				return result;
		result.merge(Checks.checkIfCuBroken(fMethod));
		if (JdtFlags.isNative(fMethod))
			result.addError(RefactoringCoreMessages.RenameMethodRefactoring_no_native); 
		return result;
	}

	protected RefactoringStatus doCheckFinalConditions(IProgressMonitor pm, CheckConditionsContext context) throws CoreException {
		try{
			RefactoringStatus result= new RefactoringStatus();
			pm.beginTask("", 9); //$NON-NLS-1$
			// TODO workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=40367
			if (!Checks.isAvailable(fMethod)) {
				result.addFatalError(RefactoringCoreMessages.RenameMethodProcessor_is_binary, JavaStatusContext.create(fMethod)); 
				return result;
			}
			result.merge(Checks.checkIfCuBroken(fMethod));
			if (result.hasFatalError())
				return result;
			pm.setTaskName(RefactoringCoreMessages.RenameMethodRefactoring_taskName_checkingPreconditions); 
			result.merge(checkNewElementName(getNewElementName()));
			
			boolean mustAnalyzeShadowing;
			IMethod[] newNameMethods= searchForDeclarationsOfClashingMethods(new SubProgressMonitor(pm, 1));
			if (newNameMethods.length == 0) {
				mustAnalyzeShadowing= false;
				pm.worked(1);
			} else {
				IType[] outerTypes= searchForOuterTypesOfReferences(newNameMethods, new SubProgressMonitor(pm, 1));
				if (outerTypes.length > 0) {
					//There exists a reference to a clashing method, where the reference is in a nested type.
					//That nested type could be a type in a ripple method's hierarchy, which could
					//cause the reference to bind to the new ripple method instead of to
					//its old binding (a method of an enclosing scope).
					//-> Getting *more* references than before -> Semantics not preserved.
					//Example: RenamePrivateMethodTests#testFail6()
					//TODO: could pass declaringTypes to the RippleMethodFinder and check whether
					//a hierarchy contains one of outerTypes (or an outer type of an outerType, recursively).
					mustAnalyzeShadowing= true;
					
				} else {
					boolean hasOldRefsInInnerTypes= true;
						//TODO: to implement this optimization:
						//- move search for references to before this check.
						//- collect references in inner types.
						//- for each reference, check for all supertypes and their enclosing types
						//(recursively), whether they declare a rippleMethod
					if (hasOldRefsInInnerTypes) {
						//There exists a reference to a ripple method in a nested type
						//of a type in the hierarchy of any ripple method.
						//When that reference is renamed, and one of the supertypes of the
						//nested type declared a method matching the new name, then
						//the renamed reference will bind to the method in its supertype,
						//since inherited methods bind stronger than methods from enclosing scopes.
						//Getting *less* references than before -> Semantics not preserved.
						//Examples: RenamePrivateMethodTests#testFail2(), RenamePrivateMethodTests#testFail5()
						mustAnalyzeShadowing= true;
					} else {
						mustAnalyzeShadowing= false;
					}
				}
			}
			
			initializeMethodsToRename(new SubProgressMonitor(pm, 1));
			pm.setTaskName(RefactoringCoreMessages.RenameMethodRefactoring_taskName_searchingForReferences); 
			fOccurrences= getOccurrences(new SubProgressMonitor(pm, 3), result);	
			pm.setTaskName(RefactoringCoreMessages.RenameMethodRefactoring_taskName_checkingPreconditions); 
			
			if (fUpdateReferences)
				result.merge(checkRelatedMethods());
			
			result.merge(analyzeCompilationUnits()); //removes CUs with syntax errors
			pm.worked(1);
			
			if (result.hasFatalError())
				return result;
			
			createChanges(new SubProgressMonitor(pm, 1), result);
			if (fUpdateReferences & mustAnalyzeShadowing)
				result.merge(analyzeRenameChanges(new SubProgressMonitor(pm, 1)));
			else
				pm.worked(1);
			
			return result;
		} finally{
			pm.done();
		}	
	}
	
	private IType[] searchForOuterTypesOfReferences(IMethod[] newNameMethods, IProgressMonitor pm) throws CoreException {
		final Set outerTypesOfReferences= new HashSet();
		SearchPattern pattern= RefactoringSearchEngine.createOrPattern(newNameMethods, IJavaSearchConstants.REFERENCES);
		IJavaSearchScope scope= createRefactoringScope(getMethod());
		SearchRequestor requestor= new SearchRequestor() {
			public void acceptSearchMatch(SearchMatch match) throws CoreException {
				if (RefactoringSearchEngine.isFiltered(match))
					return;
				IMember member= (IMember) match.getElement();
				IType declaring= member.getDeclaringType();
				if (declaring == null)
					return;
				IType outer= declaring.getDeclaringType();
				if (outer != null)
					outerTypesOfReferences.add(declaring);
			}
		};
		new SearchEngine().search(pattern, SearchUtils.getDefaultSearchParticipants(),
				scope, requestor, pm);
		return (IType[]) outerTypesOfReferences.toArray(new IType[outerTypesOfReferences.size()]);
	}

	private IMethod[] searchForDeclarationsOfClashingMethods(IProgressMonitor pm) throws CoreException {
		final List results= new ArrayList();
		SearchPattern pattern= createNewMethodPattern();
		IJavaSearchScope scope= RefactoringScopeFactory.create(getMethod().getJavaProject());
		SearchRequestor requestor= new SearchRequestor() {
			public void acceptSearchMatch(SearchMatch match) throws CoreException {
				if (RefactoringSearchEngine.isFiltered(match))
					return;
				Object method= match.getElement();
				if (method instanceof IMethod) // check for bug 90138: [refactoring] [rename] Renaming method throws internal exception
					results.add(method);
				else
					JavaPlugin.logErrorMessage("Unexpected element in search match: " + match.toString()); //$NON-NLS-1$
			}
		};
		new SearchEngine().search(pattern, SearchUtils.getDefaultSearchParticipants(), scope, requestor, pm);
		return (IMethod[]) results.toArray(new IMethod[results.size()]);
	}
	
	private SearchPattern createNewMethodPattern() throws JavaModelException {
		StringBuffer stringPattern= new StringBuffer(getNewElementName()).append('(');
		int paramCount= getMethod().getParameterNames().length;
		while (paramCount > 1) {
			stringPattern.append("*,"); //$NON-NLS-1$
			--paramCount;
		}
		if (paramCount > 0)
			stringPattern.append('*');
		stringPattern.append(')');
		
		return SearchPattern.createPattern(stringPattern.toString(), IJavaSearchConstants.METHOD,
				IJavaSearchConstants.DECLARATIONS, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
	}
	
	protected final IJavaSearchScope createRefactoringScope() throws CoreException {
		return createRefactoringScope(fMethod);
	}
	//TODO: shouldn't scope take all ripple methods into account?
	protected static final IJavaSearchScope createRefactoringScope(IMethod method) throws CoreException {
		return RefactoringScopeFactory.create(method);
	}
	
	/** */
	SearchPattern createOccurrenceSearchPattern() {
		HashSet methods= new HashSet(fMethodsToRename);
		methods.add(fMethod);
		IMethod[] ms= (IMethod[]) methods.toArray(new IMethod[methods.size()]);
		return RefactoringSearchEngine.createOrPattern(ms, IJavaSearchConstants.ALL_OCCURRENCES);
	}

	SearchResultGroup[] getOccurrences(){
		return fOccurrences;	
	}
	
	/*
	 * XXX made protected to allow overriding and working around bug 39700
	 */
	protected SearchResultGroup[] getOccurrences(IProgressMonitor pm, RefactoringStatus status) throws CoreException {
		SearchPattern pattern= createOccurrenceSearchPattern();
		return RefactoringSearchEngine.search(pattern, createRefactoringScope(),
			new MethodOccurenceCollector(getMethod().getElementName()), pm, status);	
	}

	private RefactoringStatus checkRelatedMethods() throws CoreException { 
		RefactoringStatus result= new RefactoringStatus();
		for (Iterator iter= fMethodsToRename.iterator(); iter.hasNext(); ) {
			IMethod method= (IMethod)iter.next();
			
			result.merge(Checks.checkIfConstructorName(method, getNewElementName(), method.getDeclaringType().getElementName()));
			
			String[] msgData= new String[]{method.getElementName(), JavaModelUtil.getFullyQualifiedName(method.getDeclaringType())};
			if (! method.exists()){
				result.addFatalError(Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_not_in_model, msgData)); 
				continue;
			}
			if (method.isBinary())
				result.addFatalError(Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_no_binary, msgData)); 
			if (method.isReadOnly())
				result.addFatalError(Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_no_read_only, msgData));
			if (JdtFlags.isNative(method))
				result.addError(Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_no_native_1, msgData));
		}
		return result;	
	}
	
	private RefactoringStatus analyzeCompilationUnits() throws CoreException {
		if (fOccurrences.length == 0)
			return null;
			
		RefactoringStatus result= new RefactoringStatus();
		fOccurrences= Checks.excludeCompilationUnits(fOccurrences, result);
		if (result.hasFatalError())
			return result;
		
		result.merge(Checks.checkCompileErrorsInAffectedFiles(fOccurrences));	
			
		return result;
	}
	
	//-------
	
	private RefactoringStatus analyzeRenameChanges(IProgressMonitor pm) throws CoreException {
		ICompilationUnit[] newDeclarationWCs= null;
		try {
			pm.beginTask("", 4); //$NON-NLS-1$
			RefactoringStatus result= new RefactoringStatus();
			ICompilationUnit[] declarationCUs= getDeclarationCUs();
			newDeclarationWCs= RenameAnalyzeUtil.createNewWorkingCopies(declarationCUs,
					fChangeManager, fWorkingCopyOwner, new SubProgressMonitor(pm, 1));
			
			IMethod[] wcOldMethods= new IMethod[fMethodsToRename.size()];
			IMethod[] wcNewMethods= new IMethod[fMethodsToRename.size()];
			int i= 0;
			for (Iterator iter= fMethodsToRename.iterator(); iter.hasNext(); i++) {
				IMethod method= (IMethod) iter.next();
				ICompilationUnit newCu= RenameAnalyzeUtil.findWorkingCopyForCu(newDeclarationWCs, method.getCompilationUnit());
				IType typeWc= (IType) JavaModelUtil.findInCompilationUnit(newCu, method.getDeclaringType());
				if (typeWc == null)
					continue;
				wcOldMethods[i]= getMethodInWorkingCopy(method, getCurrentElementName(), typeWc);
				wcNewMethods[i]= getMethodInWorkingCopy(method, getNewElementName(), typeWc);
			}
			
//			SearchResultGroup[] newOccurrences= findNewOccurrences(newMethods, newDeclarationWCs, new SubProgressMonitor(pm, 3));
			SearchResultGroup[] newOccurrences= batchFindNewOccurrences(wcNewMethods, wcOldMethods, newDeclarationWCs, new SubProgressMonitor(pm, 3), result);
			
			result.merge(RenameAnalyzeUtil.analyzeRenameChanges2(fChangeManager, fOccurrences, newOccurrences, getNewElementName()));
			return result;
		} finally{
			pm.done();
			if (newDeclarationWCs != null){
				for (int i= 0; i < newDeclarationWCs.length; i++) {
					newDeclarationWCs[i].discardWorkingCopy();		
				}
			}	
		}
	}
	
	//Lower memory footprint than batchFindNewOccurrences. Not used because it is too slow.
	//Final solution is maybe to do searches in chunks of ~ 50 CUs.
//	private SearchResultGroup[] findNewOccurrences(IMethod[] newMethods, ICompilationUnit[] newDeclarationWCs, IProgressMonitor pm) throws CoreException {
//		pm.beginTask("", fOccurrences.length * 2); //$NON-NLS-1$
//		
//		SearchPattern refsPattern= RefactoringSearchEngine.createOrPattern(newMethods, IJavaSearchConstants.REFERENCES);
//		SearchParticipant[] searchParticipants= SearchUtils.getDefaultSearchParticipants();
//		IJavaSearchScope scope= RefactoringScopeFactory.create(newMethods);
//		MethodOccurenceCollector requestor= new MethodOccurenceCollector(getNewElementName());
//		SearchEngine searchEngine= new SearchEngine(fWorkingCopyOwner);
//		
//		//TODO: should process only references
//		for (int j= 0; j < fOccurrences.length; j++) { //should be getReferences()
//			//cut memory peak by holding only one reference CU at a time in memory
//			ICompilationUnit originalCu= fOccurrences[j].getCompilationUnit();
//			ICompilationUnit newWc= null;
//			try {
//				ICompilationUnit wc= RenameAnalyzeUtil.findWorkingCopyForCu(newDeclarationWCs, originalCu);
//				if (wc == null) {
//					newWc= RenameAnalyzeUtil.createNewWorkingCopy(originalCu, fChangeManager, fWorkingCopyOwner,
//							new SubProgressMonitor(pm, 1));
//				}
//				searchEngine.search(refsPattern, searchParticipants, scope,	requestor, new SubProgressMonitor(pm, 1));
//			} finally {
//				if (newWc != null)
//					newWc.discardWorkingCopy();
//			}
//		}
//		SearchResultGroup[] newResults= RefactoringSearchEngine.groupByResource(requestor.getResults());
//		pm.done();
//		return newResults;
//	}

	private SearchResultGroup[] batchFindNewOccurrences(IMethod[] wcNewMethods, final IMethod[] wcOldMethods, ICompilationUnit[] newDeclarationWCs, IProgressMonitor pm, RefactoringStatus status) throws CoreException {
		pm.beginTask("", 2); //$NON-NLS-1$
		
		SearchPattern refsPattern= RefactoringSearchEngine.createOrPattern(wcNewMethods, IJavaSearchConstants.REFERENCES);
		SearchParticipant[] searchParticipants= SearchUtils.getDefaultSearchParticipants();
		IJavaSearchScope scope= RefactoringScopeFactory.create(wcNewMethods);
		
		MethodOccurenceCollector requestor;
		if (getDelegateUpdating()) {
			// There will be two new matches inside the delegate(s) (the invocation
			// and the javadoc) which are OK and must not be reported.
			// Note that except these ocurrences, the delegate bodies are empty 
			// (as they were created this way).
			requestor= new MethodOccurenceCollector(getNewElementName()) {
				public void acceptSearchMatch(SearchMatch match) throws CoreException {
					for (int i= 0; i < wcOldMethods.length; i++) 
						if (wcOldMethods[i].equals(match.getElement()))
							return;
					super.acceptSearchMatch(match);
				}
			};
		} else
			requestor= new MethodOccurenceCollector(getNewElementName());
		
		SearchEngine searchEngine= new SearchEngine(fWorkingCopyOwner);
		
		ArrayList needWCs= new ArrayList();
		HashSet declaringCUs= new HashSet(newDeclarationWCs.length);
		for (int i= 0; i < newDeclarationWCs.length; i++)
			declaringCUs.add(newDeclarationWCs[i].getPrimary());
		for (int i= 0; i < fOccurrences.length; i++) {
			ICompilationUnit cu= fOccurrences[i].getCompilationUnit();
			if (! declaringCUs.contains(cu))
				needWCs.add(cu);
		}
		ICompilationUnit[] otherWCs= null;
		try {
			otherWCs= RenameAnalyzeUtil.createNewWorkingCopies(
					(ICompilationUnit[]) needWCs.toArray(new ICompilationUnit[needWCs.size()]),
					fChangeManager, fWorkingCopyOwner, new SubProgressMonitor(pm, 1));
			searchEngine.search(refsPattern, searchParticipants, scope,	requestor, new SubProgressMonitor(pm, 1));
		} finally {
			pm.done();
			if (otherWCs != null) {
				for (int i= 0; i < otherWCs.length; i++) {
					otherWCs[i].discardWorkingCopy();
				}
			}
		}
		SearchResultGroup[] newResults= RefactoringSearchEngine.groupByCu(requestor.getResults(), status);
		return newResults;
	}
	
	private ICompilationUnit[] getDeclarationCUs() {
		Set cus= new HashSet();
		for (Iterator iter= fMethodsToRename.iterator(); iter.hasNext();) {
			IMethod method= (IMethod) iter.next();
			cus.add(method.getCompilationUnit());
		}
		return (ICompilationUnit[]) cus.toArray(new ICompilationUnit[cus.size()]);
	}
	
	private IMethod getMethodInWorkingCopy(IMethod method, String elementName, IType typeWc) throws CoreException{
		String[] paramTypeSignatures= method.getParameterTypes();
		return typeWc.getMethod(elementName, paramTypeSignatures);
	}

	//-------
	private static IMethod[] classesDeclareMethodName(ITypeHierarchy hier, List classes, IMethod method, String newName)  throws CoreException {
		Set result= new HashSet();
		IType type= method.getDeclaringType();
		List subtypes= Arrays.asList(hier.getAllSubtypes(type));
		
		int parameterCount= method.getParameterTypes().length;
		boolean isMethodPrivate= JdtFlags.isPrivate(method);
		
		for (Iterator iter= classes.iterator(); iter.hasNext(); ){
			IType clazz= (IType) iter.next();
			IMethod[] methods= clazz.getMethods();
			boolean isSubclass= subtypes.contains(clazz);
			for (int j= 0; j < methods.length; j++) {
				IMethod foundMethod= Checks.findMethod(newName, parameterCount, false, new IMethod[] {methods[j]});
				if (foundMethod == null)
					continue;
				if (isSubclass || type.equals(clazz))
					result.add(foundMethod);
				else if ((! isMethodPrivate) && (! JdtFlags.isPrivate(methods[j])))
					result.add(foundMethod);
			}
		}
		return (IMethod[]) result.toArray(new IMethod[result.size()]);
	}

	final static IMethod[] hierarchyDeclaresMethodName(IProgressMonitor pm, ITypeHierarchy hierarchy, IMethod method, String newName) throws CoreException {
		Set result= new HashSet();
		IType type= method.getDeclaringType();
		IMethod foundMethod= Checks.findMethod(newName, method.getParameterTypes().length, false, type);
		if (foundMethod != null) 
			result.add(foundMethod);

		IMethod[] foundInHierarchyClasses= classesDeclareMethodName(hierarchy, Arrays.asList(hierarchy.getAllClasses()), method, newName);
		if (foundInHierarchyClasses != null)
			result.addAll(Arrays.asList(foundInHierarchyClasses));
		
		IType[] implementingClasses= hierarchy.getImplementingClasses(type);	
		IMethod[] foundInImplementingClasses= classesDeclareMethodName(hierarchy, Arrays.asList(implementingClasses), method, newName);
		if (foundInImplementingClasses != null)
			result.addAll(Arrays.asList(foundInImplementingClasses));
		return (IMethod[]) result.toArray(new IMethod[result.size()]);	
	}
				
	//-------- changes -----

	public Change createChange(IProgressMonitor monitor) throws CoreException {
		try {
			final TextChange[] changes= fChangeManager.getAllChanges();
			final List list= new ArrayList(changes.length);
			list.addAll(Arrays.asList(changes));
			final Map arguments= new HashMap();
			String project= null;
			IJavaProject javaProject= fMethod.getJavaProject();
			if (javaProject != null)
				project= javaProject.getElementName();
			int flags= JavaRefactoringDescriptor.JAR_IMPORTABLE | JavaRefactoringDescriptor.JAR_REFACTORABLE | RefactoringDescriptor.STRUCTURAL_CHANGE;
			try {
				if (!Flags.isPrivate(fMethod.getFlags()))
					flags|= RefactoringDescriptor.MULTI_CHANGE;
			} catch (JavaModelException exception) {
				JavaPlugin.log(exception);
			}
			final IType declaring= fMethod.getDeclaringType();
			try {
				if (declaring.isAnonymous() || declaring.isLocal())
					flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
			} catch (JavaModelException exception) {
				JavaPlugin.log(exception);
			}
			final String description= Messages.format(RefactoringCoreMessages.RenameMethodProcessor_descriptor_description_short, fMethod.getElementName());
			final String header= Messages.format(RefactoringCoreMessages.RenameMethodProcessor_descriptor_description, new String[] { JavaElementLabels.getTextLabel(fMethod, JavaElementLabels.ALL_FULLY_QUALIFIED), getNewElementName()});
			final String comment= new JavaRefactoringDescriptorComment(this, header).asString();
			final JavaRefactoringDescriptor descriptor= new JavaRefactoringDescriptor(ID_RENAME_METHOD, project, description, comment, arguments, flags);
			arguments.put(JavaRefactoringDescriptor.ATTRIBUTE_INPUT, descriptor.elementToHandle(fMethod));
			arguments.put(JavaRefactoringDescriptor.ATTRIBUTE_NAME, getNewElementName());
			arguments.put(ATTRIBUTE_REFERENCES, Boolean.valueOf(fUpdateReferences).toString());
			arguments.put(ATTRIBUTE_DELEGATE, Boolean.valueOf(fDelegateUpdating).toString());
			arguments.put(ATTRIBUTE_DEPRECATE, Boolean.valueOf(fDelegateDeprecation).toString());
			return new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.RenameMethodProcessor_change_name, (Change[]) list.toArray(new Change[list.size()]));
		} finally {
			monitor.done();
		}
	}

	private TextChangeManager createChanges(IProgressMonitor pm, RefactoringStatus status) throws CoreException {
		if (!fIsComposite)
			fChangeManager.clear();
		addOccurrences(fChangeManager, pm, status);
		return fChangeManager;
	}
	
	void addOccurrences(TextChangeManager manager, IProgressMonitor pm, RefactoringStatus status) throws CoreException/*thrown in subtype*/{
		pm.beginTask("", fOccurrences.length);				 //$NON-NLS-1$
		for (int i= 0; i < fOccurrences.length; i++){
			ICompilationUnit cu= fOccurrences[i].getCompilationUnit();
			if (cu == null)	
				continue;
			
			SearchMatch[] results= fOccurrences[i].getSearchResults();

			// Split matches into declaration and non-declaration matches
			
			List declarationsInThisCu= new ArrayList();
			List referencesInThisCu= new ArrayList();
			 
			for (int j= 0; j < results.length; j++) {
				if (results[j] instanceof MethodDeclarationMatch)
					declarationsInThisCu.add(results[j]);
				else
					referencesInThisCu.add(results[j]);
			}

			// First, handle the declarations
			if (declarationsInThisCu.size() > 0) {

				if (fDelegateUpdating) {
					// Update with delegates
					CompilationUnitRewrite rewrite= new CompilationUnitRewrite(cu);
					rewrite.setResolveBindings(true);

					for (Iterator iter= declarationsInThisCu.iterator(); iter.hasNext();) {
						SearchMatch element= (SearchMatch) iter.next();
						MethodDeclaration method= ASTNodeSearchUtil.getMethodDeclarationNode((IMethod) element.getElement(), rewrite.getRoot());
						DelegateCreator creator= new DelegateMethodCreator();
						creator.setDeclareDeprecated(fDelegateDeprecation);
						creator.setDeclaration(method);
						creator.setSourceRewrite(rewrite);
						creator.setNewElementName(getNewElementName());
						creator.prepareDelegate();
						creator.createEdit();
					}
					// Need to handle all delegates first as this
					// creates a completely new change object.
					TextChange changeForThisCu= rewrite.createChange();
					changeForThisCu.setKeepPreviewEdits(true);
					manager.manage(cu, changeForThisCu);
				}

				// Update the normal methods
				for (Iterator iter= declarationsInThisCu.iterator(); iter.hasNext();) {
					SearchMatch element= (SearchMatch) iter.next();
					simpleUpdate(element, cu, manager.get(cu));
				}
			}

			// Second, handle references
			if (fUpdateReferences) {
				for (Iterator iter= referencesInThisCu.iterator(); iter.hasNext();) {
					SearchMatch element= (SearchMatch) iter.next();
					simpleUpdate(element, cu, manager.get(cu));
				}
			}
			
			pm.worked(1);
			if (pm.isCanceled())
				throw new OperationCanceledException();
		}
		pm.done();
	}

	private void simpleUpdate(SearchMatch element, ICompilationUnit cu, TextChange textChange) {
		String editName= RefactoringCoreMessages.RenameMethodRefactoring_update_occurrence;
		ReplaceEdit replaceEdit= createReplaceEdit(element, cu);
		addTextEdit(textChange, editName, replaceEdit);
	}

	protected final ReplaceEdit createReplaceEdit(SearchMatch searchResult, ICompilationUnit cu) {
		if (searchResult.isImplicit()) { // handle Annotation Element references, see bug 94062
			StringBuffer sb= new StringBuffer(getNewElementName());
			if (JavaCore.INSERT.equals(cu.getJavaProject().getOption(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATOR, true)))
				sb.append(' ');
			sb.append('=');
			if (JavaCore.INSERT.equals(cu.getJavaProject().getOption(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATOR, true)))
				sb.append(' ');
			return new ReplaceEdit(searchResult.getOffset(), 0, sb.toString());
		} else {
			return new ReplaceEdit(searchResult.getOffset(), searchResult.getLength(), getNewElementName());
		}
	}

	public RefactoringStatus initialize(RefactoringArguments arguments) {
		if (arguments instanceof JavaRefactoringArguments) {
			fInitialized= true;
			final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments;
			final String handle= extended.getAttribute(JavaRefactoringDescriptor.ATTRIBUTE_INPUT);
			if (handle != null) {
				final IJavaElement element= JavaRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
				final String refactoring= getRefactoring().getName();
				if (element instanceof IMethod) {
					final IMethod method= (IMethod) element;
					final IType declaring= method.getDeclaringType();
					if (declaring != null && declaring.exists()) {
						final IMethod[] methods= declaring.findMethods(method);
						if (methods != null && methods.length == 1 && methods[0] != null) {
							if (!methods[0].exists())
								return ScriptableRefactoring.createInputFatalStatus(methods[0], refactoring, ID_RENAME_METHOD);
							fMethod= methods[0];
							initializeWorkingCopyOwner();
						} else
							return ScriptableRefactoring.createInputFatalStatus(null, refactoring, ID_RENAME_METHOD);
					} else
						return ScriptableRefactoring.createInputFatalStatus(element, refactoring, ID_RENAME_METHOD);
				} else
					return ScriptableRefactoring.createInputFatalStatus(element, refactoring, ID_RENAME_METHOD);
			} else
				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptor.ATTRIBUTE_INPUT));
			final String name= extended.getAttribute(JavaRefactoringDescriptor.ATTRIBUTE_NAME);
			if (name != null && !"".equals(name)) //$NON-NLS-1$
				setNewElementName(name);
			else
				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptor.ATTRIBUTE_NAME));
			final String references= extended.getAttribute(ATTRIBUTE_REFERENCES);
			if (references != null) {
				fUpdateReferences= Boolean.valueOf(references).booleanValue();
			} else
				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_REFERENCES));
			final String delegate= extended.getAttribute(ATTRIBUTE_DELEGATE);
			if (delegate != null) {
				fDelegateUpdating= Boolean.valueOf(delegate).booleanValue();
			} else
				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DELEGATE));
			final String deprecate= extended.getAttribute(ATTRIBUTE_DEPRECATE);
			if (deprecate != null) {
				fDelegateDeprecation= Boolean.valueOf(deprecate).booleanValue();
			} else
				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DEPRECATE));
		} else
			return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
		return new RefactoringStatus();
	}

	protected void addTextEdit(TextChange change, String editName, ReplaceEdit replaceEdit) {
		if (fIsComposite)
			TextChangeCompatibility.addTextEdit(change, editName, replaceEdit, fCategorySet);
		else
			TextChangeCompatibility.addTextEdit(change, editName, replaceEdit);

	}
}
