--- /dev/null
+package no.uio.ifi.refaktor.change.executors;
+
+import java.util.List;
+
+import no.uio.ifi.refaktor.change.exceptions.RefaktorChangerException;
+import no.uio.ifi.refaktor.change.exceptions.VariableBindingNullException;
+import no.uio.ifi.refaktor.utils.ParseUtils;
+import no.uio.ifi.refaktor.utils.RefaktorASTNodeSearchUtil;
+
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
+import org.eclipse.jdt.internal.corext.refactoring.ParameterInfo;
+
+/**
+ * A class responsible for finding the actual target to move the given method.
+ *
+ * It does so with the help of the original target found before a
+ * method got extracted. If the original target is a field, then it
+ * is used a the new target. If it is not, then this class must search
+ * through the method parameters for the new method to find a parameter
+ * that corresponds to the binding for the original target.
+ *
+ * If no target is found after this, the there probably is an error in
+ * the analysis, and an exception is thrown.
+ */
+@SuppressWarnings("restriction")
+class MoveMethodRefactoringTargetFinder {
+
+ private final IMethod method;
+ private final IVariableBinding originalTarget;
+ private final List<ParameterInfo> parameterInfos;
+
+ public MoveMethodRefactoringTargetFinder(IMethod method, IVariableBinding originalTarget, List<ParameterInfo> parameterInfos) {
+ this.method = method;
+ this.originalTarget = originalTarget;
+ this.parameterInfos = parameterInfos;
+ }
+
+ public IVariableBinding findTarget() throws JavaModelException, RefaktorChangerException {
+ if (originalTarget.isField())
+ return originalTarget;
+
+ return searchMethodParametersForTarget();
+ }
+
+ private IVariableBinding searchMethodParametersForTarget() throws JavaModelException {
+ if (methodHasParameters()) {
+ ParameterInfo parameterInfo = getParameterInfoWithOldBinding();
+ MethodDeclaration node = RefaktorASTNodeSearchUtil.getMethodDeclarationNode(method, ParseUtils.parse(method.getCompilationUnit()));
+ for (Object declaration: node.parameters()) {
+ assert declaration instanceof SingleVariableDeclaration;
+ IVariableBinding declarationBinding = ((SingleVariableDeclaration)declaration).resolveBinding();
+ if (declarationBinding == null)
+ throw new VariableBindingNullException(this.getClass());
+
+ if (declarationMatchesParameterInfo(declarationBinding, parameterInfo))
+ return declarationBinding;
+ }
+ }
+ throw new GenericChangerException(this.getClass() + ": Could not find target for Move Method refactoring. Analysis probably wrong.");
+ }
+
+ private boolean methodHasParameters() throws JavaModelException {
+ return method.getParameters().length != 0;
+ }
+
+ private ParameterInfo getParameterInfoWithOldBinding() {
+ String originalTargetKey = originalTarget.getKey();
+
+ for (ParameterInfo parameterInfo: parameterInfos) {
+ IVariableBinding parameterInfoOldBinding = parameterInfo.getOldBinding();
+ assert parameterInfoOldBinding != null;
+ if (parameterInfoOldBinding.getKey().equals(originalTargetKey))
+ return parameterInfo;
+ }
+ assert false: "The algorithm for finding the target may be wrong. Or some part of the analysis.";
+ return null;
+ }
+
+ private boolean declarationMatchesParameterInfo(IVariableBinding declarationBinding, ParameterInfo parameterInfo) {
+ return hasMatchingTypes(declarationBinding, parameterInfo) && hasMatchingNames(declarationBinding, parameterInfo);
+ }
+
+ private boolean hasMatchingTypes(IVariableBinding declarationBinding, ParameterInfo parameterInfo) {
+ ITypeBinding declarationBindingType = declarationBinding.getType();
+ assert declarationBindingType != null;
+ ITypeBinding parameterInfoOldBindingType = parameterInfo.getOldBinding().getType();
+ assert parameterInfoOldBindingType != null;
+ return declarationBindingType.isEqualTo(parameterInfoOldBindingType);
+ }
+
+ private boolean hasMatchingNames(IVariableBinding declarationBinding, ParameterInfo parameterInfo) {
+ return declarationBinding.getName().equals(parameterInfo.getNewName());
+ }
+}
\ No newline at end of file