/*******************************************************************************
 * Copyright (c) 2000, 2020 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Samrat Dhillon <samrat.dhillon@gmail.com> - [introduce factory] Introduce Factory on an abstract class adds a statement to create an instance of that class - https://bugs.eclipse.org/bugs/show_bug.cgi?id=395016
 *     Stephan Herrmann - Contribution for Bug 463360 - [override method][null] generating method override should not create redundant null annotations
 *******************************************************************************/
package org.eclipse.jdt.internal.corext.refactoring.code;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
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.SubProgressMonitor;

import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.TextEditGroup;

import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ConstructorInvocation;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.MethodRef;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeParameter;
import org.eclipse.jdt.core.dom.VariableDeclaration;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
import org.eclipse.jdt.core.refactoring.descriptors.IntroduceFactoryDescriptor;
import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
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.internal.core.manipulation.StubUtility;
import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory;
import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2;
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2Core;
import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.Bindings;
import org.eclipse.jdt.internal.corext.dom.BodyDeclarationRewrite;
import org.eclipse.jdt.internal.corext.dom.ModifierRewrite;
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.RefactoringCoreMessages;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine2;
import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationStateChange;
import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ASTCreator;
import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
import org.eclipse.jdt.internal.corext.util.JdtFlags;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.internal.corext.util.MethodsSourcePositionComparator;
import org.eclipse.jdt.internal.corext.util.SearchUtils;

import org.eclipse.jdt.ui.JavaElementLabels;

import org.eclipse.jdt.internal.ui.JavaUIStatus;
import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;

/**
 * Refactoring class that permits the substitution of a factory method
 * for direct calls to a given constructor.
 * @author rfuhrer
 */
public class IntroduceFactoryRefactoring extends Refactoring {

	private static final String ATTRIBUTE_PROTECT= "protect"; //$NON-NLS-1$

	/**
	 * The handle for the compilation unit holding the selection that was
	 * passed into this refactoring.
	 */
	private ICompilationUnit fCUHandle;

	/**
	 * The AST for the compilation unit holding the selection that was
	 * passed into this refactoring.
	 */
	private CompilationUnit fCU;

	/**
	 * Handle for compilation unit in which the factory method/class/interface will be
	 * generated.
	 */
	private ICompilationUnit fFactoryUnitHandle;

	/**
	 * The start of the original textual selection in effect when this refactoring
	 * was initiated. If the refactoring was initiated from a structured selection
	 * (e.g. from the outline view), then this refers to the textual selection that
	 * corresponds to the structured selection item.
	 */
	private int fSelectionStart;

	/**
	 * The length of the original textual selection in effect when this refactoring
	 * was initiated. If the refactoring was initiated from a structured selection
	 * (e.g. from the outline view), then this refers to the textual selection that
	 * corresponds to the structured selection item.
	 */
	private int fSelectionLength;

	/**
	 * The AST node corresponding to the user's textual selection.
	 */
	private ASTNode fSelectedNode;

	/**
	 * The method binding for the selected constructor.
	 */
	private IMethodBinding fCtorBinding;

	/**
	 * <code>TypeDeclaration</code> for class containing the constructor to be
	 * encapsulated.
	 */
	private AbstractTypeDeclaration fCtorOwningClass;

	/**
	 * The name to be given to the generated factory method.
	 */
	private String fNewMethodName= null;

	/**
	 * An array of <code>SearchResultGroup</code>'s of all call sites
	 * that refer to the constructor signature in question.
	 */
	private SearchResultGroup[] fAllCallsTo;

	/**
	 * The class that will own the factory method/class/interface.
	 */
	private AbstractTypeDeclaration fFactoryOwningClass;

	/**
	 * The newly-generated factory method.
	 */
	private MethodDeclaration fFactoryMethod= null;

	/**
	 * An array containing the names of the constructor's formal arguments,
	 * if available, otherwise "arg1" ... "argN".
	 */
	private String[] fFormalArgNames= null;

	/**
	 * An array of <code>ITypeBinding</code>'s that describes the types of
	 * the constructor arguments, in order.
	 */
	private ITypeBinding[] fArgTypes;

	/**
	 * True iff the given constructor has a varargs signature.
	 */
	private boolean fCtorIsVarArgs;

	/**
	 * If true, change the visibility of the constructor to protected to better
	 * encapsulate it.
	 */
	private boolean fProtectConstructor= true;

	/**
	 * An <code>ImportRewrite</code> that manages imports needed to satisfy
	 * newly-introduced type references in the <code>ICompilationUnit</code>
	 * currently being rewritten during <code>createChange()</code>.
	 */
	private ImportRewrite fImportRewriter;

	/**
	 * True iff there are call sites for the constructor to be encapsulated
	 * located in binary classes.
	 */
	private boolean fCallSitesInBinaryUnits;

	/**
	 * <code>CompilationUnit</code> in which the factory is to be created.
	 */
	private CompilationUnit fFactoryCU;

	/**
	 * The fully qualified name of the factory class. This is only used
	 * if invoked from a refactoring script.
	 */
	private String fFactoryClassName;

	private int fConstructorVisibility= Modifier.PRIVATE;

	/**
	 * Creates a new <code>IntroduceFactoryRefactoring</code> with the given selection
	 * on the given compilation unit.
	 * @param cu the <code>ICompilationUnit</code> in which the user selection was made, or <code>null</code> if invoked from scripting
	 * @param selectionStart the start of the textual selection in <code>cu</code>
	 * @param selectionLength the length of the textual selection in <code>cu</code>
	 */
	public IntroduceFactoryRefactoring(ICompilationUnit cu, int selectionStart, int selectionLength) {
		Assert.isTrue(selectionStart  >= 0);
		Assert.isTrue(selectionLength >= 0);
		fSelectionStart= selectionStart;
		fSelectionLength= selectionLength;
		fCUHandle= cu;
		if (cu != null)
			initialize();
	}

    public IntroduceFactoryRefactoring(JavaRefactoringArguments arguments, RefactoringStatus status) {
   		this(null, 0, 0);
   		RefactoringStatus initializeStatus= initialize(arguments);
   		status.merge(initializeStatus);
    }

	private void initialize() {
		fCU= ASTCreator.createAST(fCUHandle, null);
	}

	/**
	 * Finds and returns the <code>ASTNode</code> for the given source text
	 * selection, if it is an entire constructor call or the class name portion
	 * of a constructor call or constructor declaration, or null otherwise.
	 * @param unit The compilation unit in which the selection was made
	 * @param offset The textual offset of the start of the selection
	 * @param length The length of the selection in characters
	 * @return ClassInstanceCreation or MethodDeclaration
	 */
	private ASTNode getTargetNode(ICompilationUnit unit, int offset, int length) {
		ASTNode node= ASTNodes.getNormalizedNode(NodeFinder.perform(fCU, offset, length));
		if (node.getNodeType() == ASTNode.CLASS_INSTANCE_CREATION)
			return node;
		if (node.getNodeType() == ASTNode.METHOD_DECLARATION && ((MethodDeclaration)node).isConstructor())
			return node;
		// we have some sub node. Make sure its the right child of the parent
		StructuralPropertyDescriptor location= node.getLocationInParent();
		ASTNode parent= node.getParent();
		if (location == ClassInstanceCreation.TYPE_PROPERTY) {
			return parent;
		} else if (location == MethodDeclaration.NAME_PROPERTY && ((MethodDeclaration)parent).isConstructor()) {
			return parent;
		}
		return null;
	}

	/**
	 * Determines what kind of AST node was selected, and returns an error status
	 * if the kind of node is inappropriate for this refactoring.
	 * @param pm
	 * @return a RefactoringStatus indicating whether the selection is valid
	 * @throws JavaModelException
	 */
	private RefactoringStatus checkSelection(IProgressMonitor pm) throws JavaModelException {
		try {
			pm.beginTask(RefactoringCoreMessages.IntroduceFactory_examiningSelection, 2);

			fSelectedNode= getTargetNode(fCUHandle, fSelectionStart, fSelectionLength);

			if (fSelectedNode == null)
				return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceFactory_notAConstructorInvocation);

			// getTargetNode() must return either a ClassInstanceCreation or a
			// constructor MethodDeclaration; nothing else.
			if (fSelectedNode instanceof ClassInstanceCreation) {
				ClassInstanceCreation classInstanceCreation= (ClassInstanceCreation)fSelectedNode;
				fCtorBinding= classInstanceCreation.resolveConstructorBinding();
			} else if (fSelectedNode instanceof MethodDeclaration) {
				MethodDeclaration methodDeclaration= (MethodDeclaration)fSelectedNode;
				fCtorBinding= methodDeclaration.resolveBinding();
			}

			if (fCtorBinding == null)
				return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceFactory_unableToResolveConstructorBinding);

			// If this constructor is of a generic type, get the generic version,
			// not some instantiation thereof.
			fCtorBinding= fCtorBinding.getMethodDeclaration();

			pm.worked(1);

			// We don't handle constructors of nested types at the moment
			if (fCtorBinding.getDeclaringClass().isNested())
				return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceFactory_unsupportedNestedTypes);

			ITypeBinding	ctorType= fCtorBinding.getDeclaringClass();
			IType			ctorOwningType= (IType) ctorType.getJavaElement();

			if (ctorOwningType.isBinary())
				// Can't modify binary CU; don't know what CU to put factory method
				return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceFactory_constructorInBinaryClass);
			if (ctorOwningType.isEnum())
				// Doesn't make sense to encapsulate enum constructors
				return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceFactory_constructorInEnum);

			// Put the generated factory method inside the type that owns the constructor
			fFactoryUnitHandle= ctorOwningType.getCompilationUnit();
			fFactoryCU= getASTFor(fFactoryUnitHandle);

			Name	ctorOwnerName= (Name) NodeFinder.perform(fFactoryCU, ctorOwningType.getNameRange());

			fCtorOwningClass= ASTNodes.getParent(ctorOwnerName, AbstractTypeDeclaration.class);
			fFactoryOwningClass= fCtorOwningClass;

			pm.worked(1);

			if (fNewMethodName == null)
				return setNewMethodName("create" + fCtorBinding.getName());//$NON-NLS-1$
			else
				return new RefactoringStatus();
		} finally {
			pm.done();
		}
	}

	/*
	 * @see org.eclipse.jdt.internal.corext.refactoring.base.Refactoring#checkActivation(org.eclipse.core.runtime.IProgressMonitor)
	 */
	@Override
	public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
		try {
			pm.beginTask(RefactoringCoreMessages.IntroduceFactory_checkingActivation, 1);

			if (!fCUHandle.isStructureKnown())
				return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceFactory_syntaxError);

			return checkSelection(new SubProgressMonitor(pm, 1));
		} finally {
			pm.done();
		}
	}

	/**
	 * @param searchHits
	 * @return the set of compilation units that will be affected by this
	 * particular invocation of this refactoring. This in general includes
	 * the class containing the constructor in question, as well as all
	 * call sites to the constructor.
	 */
	private ICompilationUnit[] collectAffectedUnits(SearchResultGroup[] searchHits) {
		Collection<ICompilationUnit>	result= new ArrayList<>();
		boolean hitInFactoryClass= false;

		for (SearchResultGroup rg : searchHits) {
			ICompilationUnit	icu= rg.getCompilationUnit();

			result.add(icu);
			if (icu.equals(fFactoryUnitHandle))
				hitInFactoryClass= true;
		}
		if (!hitInFactoryClass)
			result.add(fFactoryUnitHandle);
		return result.toArray(new ICompilationUnit[result.size()]);
	}

	/**
	 * @param ctor
	 * @param methodBinding
	 * @return a <code>SearchPattern</code> that finds all calls to the constructor
	 * identified by the argument <code>methodBinding</code>.
	 */
	private SearchPattern createSearchPattern(IMethod ctor, IMethodBinding methodBinding) {
		Assert.isNotNull(methodBinding,
				RefactoringCoreMessages.IntroduceFactory_noBindingForSelectedConstructor);

		if (ctor != null)
			return SearchPattern.createPattern(ctor, IJavaSearchConstants.REFERENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
		else { // perhaps a synthetic method? (but apparently not always... hmmm...)
			// Can't find an IMethod for this method, so build a string pattern instead
			StringBuilder	buf= new StringBuilder();

			buf.append(methodBinding.getDeclaringClass().getQualifiedName())
			   .append("(");//$NON-NLS-1$
			for(int i=0; i < fArgTypes.length; i++) {
				if (i != 0)
					buf.append(","); //$NON-NLS-1$
				buf.append(fArgTypes[i].getQualifiedName());
			}
			buf.append(")"); //$NON-NLS-1$
			return SearchPattern.createPattern(buf.toString(), IJavaSearchConstants.CONSTRUCTOR,
					IJavaSearchConstants.REFERENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
		}
	}

	private IJavaSearchScope createSearchScope(IMethod ctor, IMethodBinding binding) throws JavaModelException {
		if (ctor != null) {
			return RefactoringScopeFactory.create(ctor);
		} else {
			ITypeBinding type= Bindings.getTopLevelType(binding.getDeclaringClass());
			return RefactoringScopeFactory.create(type.getJavaElement());
		}
	}

	/**
	 * @param groups
	 * @return an array of <code>SearchResultGroup</code>'s like the argument,
	 * but omitting those groups that have no corresponding compilation unit
	 * (i.e. are binary and therefore can't be modified).
	 */
	private SearchResultGroup[] excludeBinaryUnits(SearchResultGroup[] groups) {
		Collection<SearchResultGroup>	result= new ArrayList<>();

		for (SearchResultGroup rg : groups) {
			ICompilationUnit	unit= rg.getCompilationUnit();

			if (unit != null) // ignore hits within a binary unit
				result.add(rg);
			else
				fCallSitesInBinaryUnits= true;
		}
		return result.toArray(new SearchResultGroup[result.size()]);
	}

	/**
	 * Search for all calls to the given <code>IMethodBinding</code> in the project
	 * that contains the compilation unit <code>fCUHandle</code>.
	 * @param methodBinding
	 * @param pm
	 * @param status
	 * @return an array of <code>SearchResultGroup</code>'s that identify the search matches
	 * @throws JavaModelException
	 */
	private SearchResultGroup[] searchForCallsTo(IMethodBinding methodBinding, IProgressMonitor pm, RefactoringStatus status) throws JavaModelException {
		IMethod method= (IMethod) methodBinding.getJavaElement();
		final RefactoringSearchEngine2 engine= new RefactoringSearchEngine2(createSearchPattern(method, methodBinding));
		engine.setFiltering(true, true);
		engine.setScope(createSearchScope(method, methodBinding));
		engine.setStatus(status);
		engine.searchPattern(new SubProgressMonitor(pm, 1));
		return (SearchResultGroup[]) engine.getResults();
	}

	/**
	 * Returns an array of <code>SearchResultGroup</code>'s containing all method
	 * calls in the Java project that invoke the constructor identified by the given
	 * <code>IMethodBinding</code>
	 * @param ctorBinding an <code>IMethodBinding</code> identifying a particular
	 * constructor signature to search for
	 * @param pm an <code>IProgressMonitor</code> to use during this potentially
	 * lengthy operation
	 * @param status
	 * @return an array of <code>SearchResultGroup</code>'s identifying all
	 * calls to the given constructor signature
	 * @throws JavaModelException
	 */
	private SearchResultGroup[] findAllCallsTo(IMethodBinding ctorBinding, IProgressMonitor pm, RefactoringStatus status) throws JavaModelException {
		SearchResultGroup[] groups= excludeBinaryUnits(searchForCallsTo(ctorBinding, pm, status));

		return groups;
	}

	private IType findNonPrimaryType(String fullyQualifiedName, IProgressMonitor pm, RefactoringStatus status) throws JavaModelException {
		SearchPattern p= SearchPattern.createPattern(fullyQualifiedName, IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
		final RefactoringSearchEngine2 engine= new RefactoringSearchEngine2(p);

		engine.setFiltering(true, true);
		engine.setScope(RefactoringScopeFactory.create(fCtorBinding.getDeclaringClass().getJavaElement().getJavaProject()));
		engine.setStatus(status);
		engine.searchPattern(new SubProgressMonitor(pm, 1));

		SearchResultGroup[] groups= (SearchResultGroup[]) engine.getResults();

		for (SearchResultGroup rg : groups) {
			for (SearchMatch match : rg.getSearchResults()) {
				if (match.getAccuracy() == SearchMatch.A_ACCURATE) {
					return (IType) match.getElement();
				}
			}
		}
		return null;
	}

	/*
	 * @see org.eclipse.jdt.internal.corext.refactoring.base.Refactoring#checkInput(org.eclipse.core.runtime.IProgressMonitor)
	 */
	@Override
	public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException {
		try {
			pm.beginTask(RefactoringCoreMessages.IntroduceFactory_checking_preconditions, 1);
			RefactoringStatus result= new RefactoringStatus();

			if (fFactoryClassName != null)
				result.merge(setFactoryClass(fFactoryClassName));
			if (result.hasFatalError())
				return result;
			fArgTypes= fCtorBinding.getParameterTypes();
			fCtorIsVarArgs= fCtorBinding.isVarargs();
			fAllCallsTo= findAllCallsTo(fCtorBinding, pm, result);
			fFormalArgNames= findCtorArgNames();

			ICompilationUnit[]	affectedFiles= collectAffectedUnits(fAllCallsTo);
			result.merge(Checks.validateModifiesFiles(ResourceUtil.getFiles(affectedFiles), getValidationContext(), pm));

			if (fCallSitesInBinaryUnits)
				result.merge(RefactoringStatus.createWarningStatus(RefactoringCoreMessages.IntroduceFactory_callSitesInBinaryClass));

			if(Modifier.isAbstract(fCtorBinding.getDeclaringClass().getModifiers())){
				result.merge(RefactoringStatus.createWarningStatus(RefactoringCoreMessages.IntroduceFactory_abstractClass));
			}

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

	/**
	 * @return an array containing the argument names for the constructor
	 * identified by <code>fCtorBinding</code>, if available, or default
	 * names if unavailable (e.g. if the constructor resides in a binary unit).
	 */
	private String[] findCtorArgNames() {
		int			numArgs= fCtorBinding.getParameterTypes().length;
		String[]	names= new String[numArgs];

		CompilationUnit		ctorUnit= ASTNodes.getParent(fCtorOwningClass, CompilationUnit.class);
		MethodDeclaration	ctorDecl= (MethodDeclaration) ctorUnit.findDeclaringNode(fCtorBinding.getKey());

		if (ctorDecl != null) {
			List<SingleVariableDeclaration>	formalArgs= ctorDecl.parameters();
			int i= 0;

			for(Iterator<SingleVariableDeclaration> iter= formalArgs.iterator(); iter.hasNext(); i++) {
				SingleVariableDeclaration svd= iter.next();

				names[i]= svd.getName().getIdentifier();
			}
			return names;
		}

		// Have no way of getting the formal argument names; just fake it.
		for(int i=0; i < numArgs; i++)
			names[i]= "arg" + (i+1); //$NON-NLS-1$

		return names;
	}

	/**
	 * Creates and returns a new MethodDeclaration that represents the factory method to be used in
	 * place of direct calls to the constructor in question.
	 *
	 * @param ast An AST used as a factory for various AST nodes
	 * @param ctorBinding binding for the constructor being wrapped
	 * @param unitRewriter the ASTRewrite to be used
	 * @return the new method declaration
	 * @throws CoreException if an exception occurs while accessing its corresponding resource
	 */
	private MethodDeclaration createFactoryMethod(AST ast, IMethodBinding ctorBinding, ASTRewrite unitRewriter) throws CoreException{
		MethodDeclaration		newMethod= ast.newMethodDeclaration();
		SimpleName				newMethodName= ast.newSimpleName(fNewMethodName);
		ClassInstanceCreation	newCtorCall= ast.newClassInstanceCreation();
		ReturnStatement			ret= ast.newReturnStatement();
		Block		body= ast.newBlock();
		List<Statement>		stmts= body.statements();
		String		retTypeName= ctorBinding.getName();

		createFactoryMethodSignature(ast, newMethod);

		newMethod.setName(newMethodName);
		newMethod.setBody(body);

		ITypeBinding declaringClass= fCtorBinding.getDeclaringClass();
		ITypeBinding[] ctorOwnerTypeParameters= declaringClass.getTypeParameters();

		setMethodReturnType(newMethod, retTypeName, ctorOwnerTypeParameters, ast);

		newMethod.modifiers().addAll(ASTNodeFactory.newModifiers(ast, Modifier.STATIC | Modifier.PUBLIC));

		setCtorTypeArguments(newCtorCall, retTypeName, ctorOwnerTypeParameters, ast);

		createFactoryMethodConstructorArgs(ast, newCtorCall);

		if (Modifier.isAbstract(declaringClass.getModifiers())) {
			AnonymousClassDeclaration decl= ast.newAnonymousClassDeclaration();
			CodeGenerationSettings settings= JavaPreferencesSettings.getCodeGenerationSettings(fCUHandle.getJavaProject());
			ImportRewriteContext context= new ContextSensitiveImportRewriteContext(fFactoryCU, decl.getStartPosition(), fImportRewriter);
			for (IMethodBinding unImplementedMethod : getUnimplementedMethods(declaringClass)) {
				MethodDeclaration newMethodDecl= StubUtility2.createImplementationStub(fCUHandle, unitRewriter, fImportRewriter, context,
					unImplementedMethod, unImplementedMethod.getDeclaringClass(), settings, false, new NodeFinder(fFactoryCU, decl.getStartPosition(), 0).getCoveringNode());
				decl.bodyDeclarations().add(newMethodDecl);
			}
			newCtorCall.setAnonymousClassDeclaration(decl);
		}

		ret.setExpression(newCtorCall);
		stmts.add(ret);

		return newMethod;
	}

	private IMethodBinding[] getUnimplementedMethods(ITypeBinding binding) {
		IMethodBinding[] unimplementedMethods= StubUtility2Core.getUnimplementedMethods(binding, true);
		Arrays.sort(unimplementedMethods, new MethodsSourcePositionComparator(binding));
		return unimplementedMethods;
	}

	/**
	 * Sets the type being instantiated in the given constructor call, including
     * specifying any necessary type arguments.
	 * @param newCtorCall the constructor call to modify
	 * @param ctorTypeName the simple name of the type being instantiated
	 * @param ctorOwnerTypeParameters the formal type parameters of the type being
	 * instantiated
	 * @param ast utility object used to create AST nodes
	 */
	private void setCtorTypeArguments(ClassInstanceCreation newCtorCall, String ctorTypeName, ITypeBinding[] ctorOwnerTypeParameters, AST ast) {
        if (ctorOwnerTypeParameters.length == 0) // easy, just a simple type
            newCtorCall.setType(ASTNodeFactory.newType(ast, ctorTypeName));
        else {
            Type baseType= ast.newSimpleType(ast.newSimpleName(ctorTypeName));
            ParameterizedType newInstantiatedType= ast.newParameterizedType(baseType);
            List<Type> newInstTypeArgs= newInstantiatedType.typeArguments();

			for (ITypeBinding ctorOwnerTypeParameter : ctorOwnerTypeParameters) {
				Type typeArg= ASTNodeFactory.newType(ast, ctorOwnerTypeParameter.getName());
				newInstTypeArgs.add(typeArg);
			}
            newCtorCall.setType(newInstantiatedType);
        }
	}

	/**
	 * Sets the return type of the factory method, including any necessary type
	 * arguments. E.g., for constructor <code>Foo()</code> in <code>Foo&lt;T&gt;</code>,
	 * the factory method defines a method type parameter <code>&lt;T&gt;</code> and
	 * returns a <code>Foo&lt;T&gt;</code>.
	 * @param newMethod the method whose return type is to be set
	 * @param retTypeName the simple name of the return type (without type parameters)
	 * @param ctorOwnerTypeParameters the formal type parameters of the type that the
	 * factory method instantiates (whose constructor is being encapsulated)
	 * @param ast utility object used to create AST nodes
	 */
	private void setMethodReturnType(MethodDeclaration newMethod, String retTypeName, ITypeBinding[] ctorOwnerTypeParameters, AST ast) {
        if (ctorOwnerTypeParameters.length == 0)
            newMethod.setReturnType2(ast.newSimpleType(ast.newSimpleName(retTypeName)));
        else {
            Type baseType= ast.newSimpleType(ast.newSimpleName(retTypeName));
            ParameterizedType newRetType= ast.newParameterizedType(baseType);
            List<Type> newRetTypeArgs= newRetType.typeArguments();

			for (ITypeBinding ctorOwnerTypeParameter : ctorOwnerTypeParameters) {
				Type retTypeArg= ASTNodeFactory.newType(ast, ctorOwnerTypeParameter.getName());
				newRetTypeArgs.add(retTypeArg);
			}
            newMethod.setReturnType2(newRetType);
        }
	}

	/**
	 * Creates and adds the necessary argument declarations to the given factory method.<br>
	 * An argument is needed for each original constructor argument for which the
	 * evaluation of the actual arguments across all calls was not able to be
	 * pushed inside the factory method (e.g. arguments with side-effects, references
	 * to fields if the factory method is to be static or reside in a factory class,
	 * or arguments that varied across the set of constructor calls).<br>
	 * <code>fArgTypes</code> identifies such arguments by a <code>null</code> value.
	 * @param ast utility object used to create AST nodes
	 * @param newMethod the <code>MethodDeclaration</code> for the factory method
	 */
	private void createFactoryMethodSignature(AST ast, MethodDeclaration newMethod) {
		List<SingleVariableDeclaration> argDecls= newMethod.parameters();

		for(int i=0; i < fArgTypes.length; i++) {
			SingleVariableDeclaration argDecl= ast.newSingleVariableDeclaration();
			Type argType;

			if (i == (fArgTypes.length - 1) && fCtorIsVarArgs) {
				// The trailing varargs arg has an extra array dimension, compared to
				// what we need to pass to setType()...
				argType= typeNodeForTypeBinding(fArgTypes[i].getElementType(),
						fArgTypes[i].getDimensions()-1, ast);
				argDecl.setVarargs(true);
			} else
				argType= typeNodeForTypeBinding(fArgTypes[i], 0, ast);

			argDecl.setName(ast.newSimpleName(fFormalArgNames[i]));
			argDecl.setType(argType);
			argDecls.add(argDecl);
		}

		List<Type> exceptions= newMethod.thrownExceptionTypes();

		for (ITypeBinding ctorExcept : fCtorBinding.getExceptionTypes()) {
			exceptions.add(fImportRewriter.addImport(ctorExcept, ast));
		}

        copyTypeParameters(ast, newMethod);
	}

	/**
	 * Copies the constructor's parent type's type parameters, if any, as
	 * method type parameters of the new static factory method. (Recall
	 * that static methods can't refer to type arguments of the enclosing
	 * class, since they have no instance to serve as a context.)<br>
	 * Makes sure to copy the bounds from the owning type, to ensure that the
	 * return type of the factory method satisfies the bounds of the type
	 * being instantiated.<br>
	 * E.g., for ctor Foo() in the type Foo<T extends Number>, be sure that
	 * the factory method is declared as<br>
	 * <code>static <T extends Number> Foo<T> createFoo()</code><br>
	 * and not simply<br>
	 * <code>static <T> Foo<T> createFoo()</code><br>
	 * or the compiler will bark.
	 * @param ast utility object needed to create ASTNode's for the new method
	 * @param newMethod the method onto which to copy the type parameters
	 */
	private void copyTypeParameters(AST ast, MethodDeclaration newMethod) {
		List<TypeParameter> factoryMethodTypeParms= newMethod.typeParameters();
		for (ITypeBinding ctorOwnerTypeParm : fCtorBinding.getDeclaringClass().getTypeParameters()) {
			TypeParameter newParm= ast.newTypeParameter();
			List<Type> newParmBounds= newParm.typeBounds();
			newParm.setName(ast.newSimpleName(ctorOwnerTypeParm.getName()));
			for (ITypeBinding parmTypeBound : ctorOwnerTypeParm.getTypeBounds()) {
				if (parmTypeBound.isClass() && parmTypeBound.getSuperclass() == null) {
					continue;
				}
				Type newBound= fImportRewriter.addImport(parmTypeBound, ast);
				newParmBounds.add(newBound);
			}
			factoryMethodTypeParms.add(newParm);
		}
	}

	/**
	 * @param argType
	 * @param extraDims number of extra array dimensions to add to the resulting type
	 * @param ast
	 * @return a Type that describes the given ITypeBinding. If the binding
	 * refers to an object type, use the import rewriter to determine whether
	 * the reference requires a new import, or instead needs to be qualified.<br>
	 * Like ASTNodeFactory.newType(), but for the handling of imports.
	 */
	private Type typeNodeForTypeBinding(ITypeBinding argType, int extraDims, AST ast) {
		if (extraDims > 0) {
			return ast.newArrayType(typeNodeForTypeBinding(argType, 0, ast), extraDims);

		} else if (argType.isArray()) {
			Type elementType= typeNodeForTypeBinding(argType.getElementType(), extraDims, ast);
			return ast.newArrayType(elementType, argType.getDimensions());

		} else {
			return fImportRewriter.addImport(argType, ast);
		}
	}

	/**
	 * Create the list of actual arguments to the constructor call that is
	 * encapsulated inside the factory method, and associate the arguments
	 * with the given constructor call object.
	 * @param ast utility object used to create AST nodes
	 * @param newCtorCall the newly-generated constructor call to be wrapped inside
	 * the factory method
	 */
	private void createFactoryMethodConstructorArgs(AST ast, ClassInstanceCreation newCtorCall) {
		List<Expression> argList= newCtorCall.arguments();

		for(int i=0; i < fArgTypes.length; i++) {
			ASTNode ctorArg= ast.newSimpleName(fFormalArgNames[i]);

			argList.add((Expression) ctorArg);
		}
	}

	/**
	 * Updates the constructor call.
	 *
	 * @param ctorCall the ClassInstanceCreation to be marked as replaced
	 * @param unitRewriter the AST rewriter
	 * @param gd the edit group to use
	 */
	private void rewriteFactoryMethodCall(ClassInstanceCreation ctorCall, ASTRewrite unitRewriter, TextEditGroup gd) {
		AST ast= unitRewriter.getAST();
		MethodInvocation factoryMethodCall= ast.newMethodInvocation();

		ASTNode ctorCallParent= ctorCall.getParent();
		StructuralPropertyDescriptor ctorCallLocation= ctorCall.getLocationInParent();
		if (ctorCallLocation instanceof ChildListPropertyDescriptor) {
			ListRewrite ctorCallParentListRewrite= unitRewriter.getListRewrite(ctorCallParent, (ChildListPropertyDescriptor)ctorCallLocation);
			int index= ctorCallParentListRewrite.getOriginalList().indexOf(ctorCall);
			ctorCall= (ClassInstanceCreation)ctorCallParentListRewrite.getRewrittenList().get(index);
		} else {
			ctorCall= (ClassInstanceCreation)unitRewriter.get(ctorCallParent, ctorCallLocation);
		}

		ListRewrite actualFactoryArgs= unitRewriter.getListRewrite(factoryMethodCall, MethodInvocation.ARGUMENTS_PROPERTY);
		ListRewrite actualCtorArgs= unitRewriter.getListRewrite(ctorCall, ClassInstanceCreation.ARGUMENTS_PROPERTY);

		// Need to use a qualified name for the factory method if we're not
		// in the context of the class holding the factory.
		AbstractTypeDeclaration	callOwner= ASTNodes.getParent(ctorCall, AbstractTypeDeclaration.class);
		ITypeBinding callOwnerBinding= callOwner.resolveBinding();

		if (callOwnerBinding == null || !Bindings.equals(callOwner.resolveBinding(), fFactoryOwningClass.resolveBinding())) {
			String qualifier= fImportRewriter.addImport(fFactoryOwningClass.resolveBinding());
			factoryMethodCall.setExpression(ASTNodeFactory.newName(ast, qualifier));
		}

		factoryMethodCall.setName(ast.newSimpleName(fNewMethodName));

		List<Expression> actualCtorArgsList= actualCtorArgs.getRewrittenList();
		for (Expression actualCtorArg : actualCtorArgsList) {
			ASTNode movedArg;
			if (ASTNodes.isExistingNode(actualCtorArg)) {
				movedArg= unitRewriter.createMoveTarget(actualCtorArg);
			} else {
				unitRewriter.remove(actualCtorArg, gd);
				movedArg= actualCtorArg;
			}

			actualFactoryArgs.insertLast(movedArg, gd);
		}

		unitRewriter.replace(ctorCall, factoryMethodCall, gd);
	}

	/**
	 * @param unit
	 * @return true iff the given <code>ICompilationUnit</code> is the unit
	 * containing the original constructor
	 */
	private boolean isConstructorUnit(ICompilationUnit unit) {
		return unit.equals(ASTCreator.getCu(fCtorOwningClass));
	}

	/**
	 * @return true iff we should actually change the original constructor's
	 * visibility to <code>protected</code>. This takes into account the user-
	 * requested mode and whether the constructor's compilation unit is in
	 * source form.
	 */
	private boolean shouldProtectConstructor() {
		return fProtectConstructor && fCtorOwningClass != null;
	}

	/**
	 * Creates and adds the necessary change to make the constructor method protected.
	 * @param unitAST
	 * @param unitRewriter
	 * @param declGD
	 * @return false iff the constructor didn't exist (i.e. was implicit)
	 */
	private boolean protectConstructor(CompilationUnit unitAST, ASTRewrite unitRewriter, TextEditGroup declGD) {
		MethodDeclaration constructor= (MethodDeclaration) unitAST.findDeclaringNode(fCtorBinding.getKey());

		// No need to rewrite the modifiers if the visibility is what we already want it to be.
		if (constructor == null || (JdtFlags.getVisibilityCode(constructor)) == fConstructorVisibility)
			return false;
		ModifierRewrite.create(unitRewriter, constructor).setVisibility(fConstructorVisibility, declGD);
		return true;
	}

	/**
	 * Add all changes necessary on the <code>ICompilationUnit</code> in the given
	 * <code>SearchResultGroup</code> to implement the refactoring transformation
	 * to the given <code>CompilationUnitChange</code>.
	 * @param rg the <code>SearchResultGroup</code> for which changes should be created
	 * @param unitHandle
	 * @param unitChange the CompilationUnitChange object for the compilation unit in question
	 * @return <code>true</code> iff a change has been added
	 * @throws CoreException
	 */
	private boolean addAllChangesFor(SearchResultGroup rg, ICompilationUnit	unitHandle, CompilationUnitChange unitChange) throws CoreException {
//		ICompilationUnit	unitHandle= rg.getCompilationUnit();
		Assert.isTrue(rg == null || rg.getCompilationUnit() == unitHandle);
		CompilationUnit		unit= getASTFor(unitHandle);
		ASTRewrite			unitRewriter= ASTRewrite.create(unit.getAST());
		MultiTextEdit		root= new MultiTextEdit();
		boolean				someChange= false;

		unitChange.setEdit(root);
		fImportRewriter= StubUtility.createImportRewrite(unit, true);

		// First create the factory method
		if (unitHandle.equals(fFactoryUnitHandle)) {
			TextEditGroup	factoryGD= new TextEditGroup(RefactoringCoreMessages.IntroduceFactory_addFactoryMethod);

			createFactoryChange(unitRewriter, unit, factoryGD);
			unitChange.addTextEditGroup(factoryGD);
			someChange= true;
		}

		// Now rewrite all the constructor calls to use the factory method
		if (rg != null)
			if (replaceConstructorCalls(rg, unit, unitRewriter, unitChange))
				someChange= true;

		// Finally, make the constructor private, if requested.
		if (shouldProtectConstructor() && isConstructorUnit(unitHandle)) {
			TextEditGroup	declGD= new TextEditGroup(RefactoringCoreMessages.IntroduceFactory_protectConstructor);

			if (protectConstructor(unit, unitRewriter, declGD)) {
				unitChange.addTextEditGroup(declGD);
				someChange= true;
			}
		}

		if (someChange) {
			root.addChild(unitRewriter.rewriteAST());
			root.addChild(fImportRewriter.rewriteImports(null));
		}

		return someChange;
	}

	/**
	 * @param unitHandle
	 * @return an AST for the given compilation unit handle.<br>
	 * If this is the unit containing the selection or the unit in which the factory
	 * is to reside, checks the appropriate field (<code>fCU</code> or <code>fFactoryCU</code>,
	 * respectively) and initializes the field with a new AST only if not already done.
	 */
	private CompilationUnit getASTFor(ICompilationUnit unitHandle) {
		if (unitHandle.equals(fCUHandle)) { // is this the unit containing the selection?
			if (fCU == null) {
				fCU= ASTCreator.createAST(unitHandle, null);
				if (fCUHandle.equals(fFactoryUnitHandle)) // if selection unit and factory unit are the same...
					fFactoryCU= fCU; // ...make sure the factory unit gets initialized
			}
			return fCU;
		} else if (unitHandle.equals(fFactoryUnitHandle)) { // is this the "factory unit"?
			if (fFactoryCU == null)
				fFactoryCU= ASTCreator.createAST(unitHandle, null);
			return fFactoryCU;
		} else
			return ASTCreator.createAST(unitHandle, null);
	}

	/**
	 * Use the given <code>ASTRewrite</code> to replace direct calls to the constructor with calls
	 * to the newly-created factory method.
	 *
	 * @param rg the <code>SearchResultGroup</code> indicating all of the constructor references
	 * @param unit the <code>CompilationUnit</code> to be rewritten
	 * @param unitRewriter the rewriter
	 * @param unitChange the compilation unit change
	 * @throws CoreException
	 * @return true iff at least one constructor call site was rewritten.
	 */
	private boolean replaceConstructorCalls(SearchResultGroup rg, CompilationUnit unit, ASTRewrite unitRewriter, CompilationUnitChange unitChange) throws CoreException {
		Assert.isTrue(ASTCreator.getCu(unit).equals(rg.getCompilationUnit()));
		SearchMatch[] hits= rg.getSearchResults();
		/*
		 * Sort by descending offset, such that nested constructor calls are processed first. This
		 * is necessary, since they can only be moved into the factory method invocation after they
		 * have been rewritten.
		 */
		Arrays.sort(hits, (m1, m2) -> m2.getOffset() - m1.getOffset());

		boolean someCallPatched= false;

		for (SearchMatch hit : hits) {
			ASTNode ctrCall= getCtorCallAt(hit.getOffset(), hit.getLength(), unit);
			if (ctrCall instanceof ClassInstanceCreation) {
				TextEditGroup gd= new TextEditGroup(RefactoringCoreMessages.IntroduceFactory_replaceCalls);

				rewriteFactoryMethodCall((ClassInstanceCreation) ctrCall, unitRewriter, gd);
				unitChange.addTextEditGroup(gd);
				someCallPatched= true;
			} else if (ctrCall instanceof MethodRef) {
				TextEditGroup gd= new TextEditGroup(RefactoringCoreMessages.IntroduceFactoryRefactoring_replaceJavadocReference);

				rewriteJavadocReference((MethodRef) ctrCall, unitRewriter, gd);
				unitChange.addTextEditGroup(gd);
				someCallPatched= true;
			}
		}
		return someCallPatched;
	}

	private void rewriteJavadocReference(MethodRef javadocRef, ASTRewrite unitRewriter, TextEditGroup gd) {
		AST ast= unitRewriter.getAST();
		unitRewriter.replace(javadocRef.getName(), ast.newSimpleName(fNewMethodName), gd);
	}

	/**
	 * Look "in the vicinity" of the given range to find the <code>ClassInstanceCreation</code>
	 * node that this search hit identified. Necessary because the <code>SearchEngine</code>
	 * doesn't always cough up text extents that <code>NodeFinder.perform()</code> agrees with.
	 * @param start
	 * @param length
	 * @param unitAST
	 * @return return a {@link ClassInstanceCreation} or a {@link MethodRef} or <code>null</code> if this is really a constructor->constructor call (e.g. "this(...)")
	 * @throws CoreException
	 */
	private ASTNode getCtorCallAt(int start, int length, CompilationUnit unitAST) throws CoreException {
		ICompilationUnit unitHandle= ASTCreator.getCu(unitAST);
		ASTNode node= NodeFinder.perform(unitAST, start, length);

		if (node == null)
			throw new CoreException(JavaUIStatus.createError(IStatus.ERROR,
					Messages.format(RefactoringCoreMessages.IntroduceFactory_noASTNodeForConstructorSearchHit,
							new Object[] { Integer.toString(start), Integer.toString(start + length),
							    BasicElementLabels.getJavaCodeString(unitHandle.getSource().substring(start, start + length)),
								BasicElementLabels.getFileName(unitHandle) }),
					null));

		if (node instanceof ClassInstanceCreation) {
			if (((ClassInstanceCreation)node).getAnonymousClassDeclaration() != null) {
				// Cannot replace anonymous inner class, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=250660
				fConstructorVisibility= Modifier.PROTECTED;
				return null;
			}
			return node;
		} else if (node instanceof VariableDeclaration) {
			Expression	init= ((VariableDeclaration) node).getInitializer();

			if (init instanceof ClassInstanceCreation) {
				return init;
			} else if (init != null)
				throw new CoreException(JavaUIStatus.createError(IStatus.ERROR,
						Messages.format(RefactoringCoreMessages.IntroduceFactory_unexpectedInitializerNodeType,
								new Object[] { BasicElementLabels.getJavaCodeString(init.toString()), BasicElementLabels.getFileName(unitHandle) }),
						null));
			else
				throw new CoreException(JavaUIStatus.createError(IStatus.ERROR,
						Messages.format(RefactoringCoreMessages.IntroduceFactory_noConstructorCallNodeInsideFoundVarbleDecl,
								BasicElementLabels.getJavaCodeString(node.toString())),
						null));
		} else if (node instanceof ConstructorInvocation) {
			// This is a call we can bypass; it's from one constructor flavor
			// to another flavor on the same class.
			return null;
		} else if (node instanceof SuperConstructorInvocation) {
			// This is a call we can bypass; it's from one constructor flavor
			// to another flavor on the same class.
			fConstructorVisibility= Modifier.PROTECTED;
			return null;
		} else if (node instanceof ExpressionStatement) {
			Expression	expr= ((ExpressionStatement) node).getExpression();

			if (expr instanceof ClassInstanceCreation)
				return expr;
			else
				throw new CoreException(JavaUIStatus.createError(IStatus.ERROR,
						Messages.format(RefactoringCoreMessages.IntroduceFactory_unexpectedASTNodeTypeForConstructorSearchHit,
								new Object[] { BasicElementLabels.getJavaCodeString(expr.toString()), BasicElementLabels.getFileName(unitHandle) }),
						null));
		} else if (node instanceof SimpleName && (node.getParent() instanceof MethodDeclaration || node.getParent() instanceof AbstractTypeDeclaration)) {
			// We seem to have been given a hit for an implicit call to the base-class constructor.
			// Do nothing with this (implicit) call, but have to make sure we make the derived class
			// doesn't lose access to the base-class constructor (so make it 'protected', not 'private').
			fConstructorVisibility= Modifier.PROTECTED;
			return null;
		} else if (node instanceof MethodRef) {
			return node;
		} else
			throw new CoreException(JavaUIStatus.createError(IStatus.ERROR,
					Messages.format(RefactoringCoreMessages.IntroduceFactory_unexpectedASTNodeTypeForConstructorSearchHit,
							new Object[] { BasicElementLabels.getJavaElementName(node.getClass().getName() + "('" + node.toString() + "')"), BasicElementLabels.getFileName(unitHandle) }), //$NON-NLS-1$ //$NON-NLS-2$
					null));
	}

	/**
	 * Perform the AST rewriting necessary on the given <code>CompilationUnit</code> to create the
	 * factory method. The method will reside on the type identified by
	 * <code>fFactoryOwningClass</code>.
	 *
	 * @param unitRewriter the ASTRewrite to be used
	 * @param unit the <code>CompilationUnit</code> where factory method will be created
	 * @param gd the <code>GroupDescription</code> to associate with the changes made
	 * @throws CoreException if an exception occurs while accessing its corresponding resource
	 */
	private void createFactoryChange(ASTRewrite unitRewriter, CompilationUnit unit, TextEditGroup gd) throws CoreException {
		// ================================================================================
		// First add the factory itself (method, class, and interface as needed/directed by user)
		AST				ast= unit.getAST();

		fFactoryMethod= createFactoryMethod(ast, fCtorBinding, unitRewriter);

		AbstractTypeDeclaration	factoryOwner= (AbstractTypeDeclaration) unit.findDeclaringNode(fFactoryOwningClass.resolveBinding().getKey());
		fImportRewriter.addImport(fCtorOwningClass.resolveBinding());

		int	idx= BodyDeclarationRewrite.getInsertionIndex(fFactoryMethod, factoryOwner.bodyDeclarations());

		if (idx < 0) idx= 0; // Guard against bug in getInsertionIndex()
		unitRewriter.getListRewrite(factoryOwner, factoryOwner.getBodyDeclarationsProperty()).insertAt(fFactoryMethod, idx, gd);
	}

	@Override
	public Change createChange(IProgressMonitor pm) throws CoreException {
		try {
			pm.beginTask(RefactoringCoreMessages.IntroduceFactory_createChanges, fAllCallsTo.length);
			final ITypeBinding binding= fFactoryOwningClass.resolveBinding();
			final Map<String, String> arguments= new HashMap<>();
			String project= null;
			IJavaProject javaProject= fCUHandle.getJavaProject();
			if (javaProject != null)
				project= javaProject.getElementName();
			int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE;
			if (binding.isNested() && !binding.isMember())
				flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
			final String description= Messages.format(RefactoringCoreMessages.IntroduceFactoryRefactoring_descriptor_description_short, BasicElementLabels.getJavaElementName(fCtorOwningClass.getName().getIdentifier()));
			final String header= Messages.format(RefactoringCoreMessages.IntroduceFactory_descriptor_description, new String[] { BasicElementLabels.getJavaElementName(fNewMethodName), BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_FULLY_QUALIFIED), BindingLabelProvider.getBindingLabel(fCtorBinding, JavaElementLabels.ALL_FULLY_QUALIFIED)});
			final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header);
			comment.addSetting(Messages.format(RefactoringCoreMessages.IntroduceFactoryRefactoring_original_pattern, BindingLabelProvider.getBindingLabel(fCtorBinding, JavaElementLabels.ALL_FULLY_QUALIFIED)));
			comment.addSetting(Messages.format(RefactoringCoreMessages.IntroduceFactoryRefactoring_factory_pattern, BasicElementLabels.getJavaElementName(fNewMethodName)));
			comment.addSetting(Messages.format(RefactoringCoreMessages.IntroduceFactoryRefactoring_owner_pattern, BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_FULLY_QUALIFIED)));
			if (fProtectConstructor)
				comment.addSetting(RefactoringCoreMessages.IntroduceFactoryRefactoring_declare_private);
			final IntroduceFactoryDescriptor descriptor= RefactoringSignatureDescriptorFactory.createIntroduceFactoryDescriptor(project, description, comment.asString(), arguments, flags);
			arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT, JavaRefactoringDescriptorUtil.elementToHandle(project, fCUHandle));
			arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME, fNewMethodName);
			arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + 1, JavaRefactoringDescriptorUtil.elementToHandle(project, binding.getJavaElement()));
			arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION, Integer.toString(fSelectionStart) + " " + Integer.toString(fSelectionLength)); //$NON-NLS-1$
			arguments.put(ATTRIBUTE_PROTECT, Boolean.toString(fProtectConstructor));
			final DynamicValidationStateChange result= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.IntroduceFactory_name);
			boolean hitInFactoryClass= false;
			boolean hitInCtorClass= false;
			for (SearchResultGroup rg : fAllCallsTo) {
				ICompilationUnit unitHandle= rg.getCompilationUnit();
				CompilationUnitChange cuChange= new CompilationUnitChange(getName(), unitHandle);

				if (addAllChangesFor(rg, unitHandle, cuChange))
					result.add(cuChange);

				if (unitHandle.equals(fFactoryUnitHandle))
					hitInFactoryClass= true;
				if (unitHandle.equals(ASTCreator.getCu(fCtorOwningClass)))
					hitInCtorClass= true;

				pm.worked(1);
				if (pm.isCanceled())
					throw new OperationCanceledException();
			}
			if (!hitInFactoryClass) { // Handle factory class if no search hits there
				CompilationUnitChange cuChange= new CompilationUnitChange(getName(), fFactoryUnitHandle);
				addAllChangesFor(null, fFactoryUnitHandle, cuChange);
				result.add(cuChange);
			}
			if (!hitInCtorClass && !fFactoryUnitHandle.equals(ASTCreator.getCu(fCtorOwningClass))) { // Handle constructor-owning class if no search hits there
				CompilationUnitChange cuChange= new CompilationUnitChange(getName(), ASTCreator.getCu(fCtorOwningClass));
				addAllChangesFor(null, ASTCreator.getCu(fCtorOwningClass), cuChange);
				result.add(cuChange);
			}
			return result;
		} finally {
			pm.done();
		}
	}

	@Override
	public String getName() {
		return RefactoringCoreMessages.IntroduceFactory_name;
	}

	/**
	 * Returns the name to be used for the generated factory method.
	 * @return the new method name
	 */
	public String getNewMethodName() {
		return fNewMethodName;
	}

	/**
	 * Sets the name to be used for the generated factory method.<br>
	 * Returns a <code>RefactoringStatus</code> that indicates whether the
	 * given name is valid for the new factory method.
	 * @param newMethodName the name to be used for the generated factory method
	 * @return the resulting status
	 */
	public RefactoringStatus setNewMethodName(String newMethodName) {
		Assert.isNotNull(newMethodName);
		fNewMethodName = newMethodName;

		RefactoringStatus stat= Checks.checkMethodName(newMethodName, fCUHandle);

		stat.merge(isUniqueMethodName(newMethodName));

		return stat;
	}

	/**
	 * @param methodName
	 * @return a <code>RefactoringStatus</code> that identifies whether the
	 * the name <code>newMethodName</code> is available to use as the name of
	 * the new factory method within the factory-owner class (either a to-be-
	 * created factory class or the constructor-owning class, depending on the
	 * user options).
	 */
	private RefactoringStatus isUniqueMethodName(String methodName) {
		ITypeBinding declaringClass= fCtorBinding.getDeclaringClass();
		if (Bindings.findMethodInType(declaringClass, methodName, fCtorBinding.getParameterTypes()) != null) {
			String format= Messages.format(RefactoringCoreMessages.IntroduceFactory_duplicateMethodName, BasicElementLabels.getJavaElementName(methodName));
			return RefactoringStatus.createErrorStatus(format);
		}
 		return new RefactoringStatus();
	}

	/**
	 * Returns true iff the selected constructor can be protected.
	 * @return return <code>true</code> if the constructor can be made protected
	 */
	public boolean canProtectConstructor() {
		return !fCtorBinding.isSynthetic() && fFactoryCU.findDeclaringNode(fCtorBinding.getKey()) != null;
	}

	/**
	 * If the argument is true, change the visibility of the constructor to
	 * <code>protected</code>, thereby encapsulating it.
	 * @param protectConstructor
	 */
	public void setProtectConstructor(boolean protectConstructor) {
		fProtectConstructor = protectConstructor;
	}

	/**
	 * Returns the project on behalf of which this refactoring was invoked.
	 * @return returns the Java project
	 */
	public IJavaProject getProject() {
		return fCUHandle.getJavaProject();
	}

	/**
	 * Sets the class on which the generated factory method is to be placed.
	 * @param fullyQualifiedTypeName an <code>IType</code> referring to an existing class
	 * @return return the resulting status
	 */
	public RefactoringStatus setFactoryClass(String fullyQualifiedTypeName) {
		IType factoryType;

		try {
			factoryType= findFactoryClass(fullyQualifiedTypeName);
			if (factoryType == null)
				return RefactoringStatus.createErrorStatus(Messages.format(RefactoringCoreMessages.IntroduceFactory_noSuchClass, BasicElementLabels.getJavaElementName(fullyQualifiedTypeName)));

			if (factoryType.isAnnotation())
				return RefactoringStatus.createErrorStatus(RefactoringCoreMessages.IntroduceFactory_cantPutFactoryMethodOnAnnotation);
			if (factoryType.isInterface())
				return RefactoringStatus.createErrorStatus(RefactoringCoreMessages.IntroduceFactory_cantPutFactoryMethodOnInterface);
		} catch (JavaModelException e) {
			return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceFactory_cantCheckForInterface);
		}

		ICompilationUnit	factoryUnitHandle= factoryType.getCompilationUnit();

		if (factoryType.isBinary())
			return RefactoringStatus.createErrorStatus(RefactoringCoreMessages.IntroduceFactory_cantPutFactoryInBinaryClass);
		else {
			try {
				if (!fFactoryUnitHandle.equals(factoryUnitHandle)) {
					fFactoryCU= getASTFor(factoryUnitHandle);
					fFactoryUnitHandle= factoryUnitHandle;
				}
				fFactoryOwningClass= ASTNodes.getParent(NodeFinder.perform(fFactoryCU, factoryType.getNameRange()), AbstractTypeDeclaration.class);

				String factoryPkg= factoryType.getPackageFragment().getElementName();
				String ctorPkg= fCtorOwningClass.resolveBinding().getPackage().getName();

				if (!factoryPkg.equals(ctorPkg))
					fConstructorVisibility= Modifier.PUBLIC;
				else if (fFactoryOwningClass != fCtorOwningClass)
					fConstructorVisibility= 0; // No such thing as Modifier.PACKAGE...


				if (fFactoryOwningClass != fCtorOwningClass)
					fConstructorVisibility= 0; // No such thing as Modifier.PACKAGE...

			} catch (JavaModelException e) {
				return RefactoringStatus.createFatalErrorStatus(e.getMessage());
			}
			return new RefactoringStatus();
		}
	}

	/**
	 * Finds the factory class associated with the fully qualified name.
	 * @param fullyQualifiedTypeName the fully qualified type name
	 * @return the factory class, or <code>null</code> if not found
	 * @throws JavaModelException if an error occurs while finding the factory class
	 */
	private IType findFactoryClass(String fullyQualifiedTypeName) throws JavaModelException {
		IType factoryType= getProject().findType(fullyQualifiedTypeName);
		if (factoryType == null) // presumably a non-primary type; try the search engine
			factoryType= findNonPrimaryType(fullyQualifiedTypeName, new NullProgressMonitor(), new RefactoringStatus());
		return factoryType;
	}

	/**
	 * Returns the name of the class on which the generated factory method is
	 * to be placed.
	 * @return return the factory class name
	 */
	public String getFactoryClassName() {
		return fFactoryOwningClass.resolveBinding().getQualifiedName();
	}

	private RefactoringStatus initialize(JavaRefactoringArguments arguments) {
		final String selection= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION);
		if (selection != null) {
			int offset= -1;
			int length= -1;
			final StringTokenizer tokenizer= new StringTokenizer(selection);
			if (tokenizer.hasMoreTokens())
				offset= Integer.parseInt(tokenizer.nextToken());
			if (tokenizer.hasMoreTokens())
				length= Integer.parseInt(tokenizer.nextToken());
			if (offset >= 0 && length >= 0) {
				fSelectionStart= offset;
				fSelectionLength= length;
			} else
				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object[] { selection, JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION}));
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION));
		String handle= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
		if (handle != null) {
			final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(arguments.getProject(), handle, false);
			if (element == null || !element.exists() || element.getElementType() != IJavaElement.COMPILATION_UNIT)
				return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getName(), IJavaRefactorings.INTRODUCE_FACTORY);
			else {
				fCUHandle= (ICompilationUnit) element;
	        	initialize();
			}
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
		handle= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + 1);
		if (handle != null) {
			final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(arguments.getProject(), handle, false);
			if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE)
				return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getName(), IJavaRefactorings.INTRODUCE_FACTORY);
			else {
				final IType type= (IType) element;
				fFactoryClassName= type.getFullyQualifiedName();
			}
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
		final String name= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME);
		if (name != null && !"".equals(name)) //$NON-NLS-1$
			fNewMethodName= name;
		else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME));
		final String protect= arguments.getAttribute(ATTRIBUTE_PROTECT);
		if (protect != null) {
			fProtectConstructor= Boolean.parseBoolean(protect);
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_PROTECT));
		return new RefactoringStatus();
	}
}
