package org.eclipse.objectteams.otdt.internal.refactoring.otrefactorings.inlinecallin;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IFile;
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.OperationCanceledException;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
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.JavaConventions;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.AbstractMethodMappingDeclaration;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.BaseCallMessageSend;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.CallinMappingDeclaration;
import org.eclipse.jdt.core.dom.CalloutMappingDeclaration;
import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IExtendedModifier;
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.MethodSpec;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
import org.eclipse.jdt.core.dom.ParameterMapping;
import org.eclipse.jdt.core.dom.PrimitiveType;
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.Type;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
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.codemanipulation.StubUtility;
import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
import org.eclipse.jdt.internal.corext.refactoring.structure.ImportRewriteUtil;
import org.eclipse.jdt.internal.corext.refactoring.structure.ReferenceFinderUtil;
import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
import org.eclipse.jdt.ui.JavaElementLabels;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.CompositeChange;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.TextFileChange;
import org.eclipse.objectteams.otdt.core.ICallinMapping;
import org.eclipse.objectteams.otdt.core.ICalloutMapping;
import org.eclipse.objectteams.otdt.core.ICalloutToFieldMapping;
import org.eclipse.objectteams.otdt.core.IMethodMapping;
import org.eclipse.objectteams.otdt.core.IOTJavaElement;
import org.eclipse.objectteams.otdt.core.IRoleType;
import org.eclipse.objectteams.otdt.core.OTModelManager;
import org.eclipse.objectteams.otdt.internal.refactoring.corext.rename.BaseCallFinder;
import org.eclipse.objectteams.otdt.internal.refactoring.otrefactorings.OTRefactoringMessages;
import org.eclipse.objectteams.otdt.internal.refactoring.util.RefactoringUtil;
import org.eclipse.osgi.util.NLS;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.text.edits.TextEditGroup;

@SuppressWarnings("restriction")
public class InlineCallinRefactoring extends Refactoring {
	
	private IMethod fRoleMethod;
	
	private String fRoleMethodName;
	
	private CallinBaseMethodInfo[] fCallinBaseMethodInfos;

	private boolean fDeleteRoleMethod;

	private CompilationUnit fRootBase;

	private AST fBaseAST;

	private ImportRewrite fBaseImportRewriter;

	private ICompilationUnit fBaseCUnit;
	
	private CallinBaseMethodInfo[] fTargetBaseMethods;

	private ICompilationUnit fRoleCUnit;

	private CompilationUnit fRootRole;

	private AST fRoleAST;

	private IType fRoleType;

	private TextFileChange fBaseTextFileChange;

	private TextFileChange fRoleTextFileChange;

	private List<ICallinMapping> fBoundCallinMappings;

	private IType fBaseType;

	private ASTRewrite fBaseRewrite;

	private ASTRewrite fRoleRewrite;

	private Object fCachedBaseMethodInfo = null;

	private Set<String> fCachedTunneledParameters = null;
	
	public InlineCallinRefactoring() {
	}

	public InlineCallinRefactoring(IMethod roleMethod) {
		fRoleMethod = roleMethod;
	}

	public InlineCallinRefactoring(IMethod roleMethod, ICallinMapping[] callinMapping, IMethod[] baseMethods) {
		fBaseType = baseMethods[0].getDeclaringType();
		
		List<CallinBaseMethodInfo> methodInfos = new ArrayList<CallinBaseMethodInfo>();
		for (int i = 0; i < baseMethods.length; i++) {
			methodInfos.add(new CallinBaseMethodInfo(baseMethods[i], callinMapping[i]));
		}
		setBaseMethods(methodInfos.toArray(new CallinBaseMethodInfo[methodInfos.size()]));

		fRoleMethod = roleMethod;
	}

	public IMethod getRoleMethod() {
		return fRoleMethod;
	}
	
	public IMethod[] getBoundBaseMethods() throws JavaModelException {
		List<IMethod> boundBaseMethods = new ArrayList<IMethod>();
		for (ICallinMapping mapping : fBoundCallinMappings) {
			boundBaseMethods.addAll(Arrays.asList(mapping.getBoundBaseMethods()));
		}
		return boundBaseMethods.toArray(new IMethod[boundBaseMethods.size()]);
	}

	public List<ICallinMapping> getBoundCallinMappings() {
		return fBoundCallinMappings;
	}

	@Override
	public String getName() {
		return OTRefactoringMessages.InlineCallin_inlineCallin_name;
	}

	public void setRoleMethodName(String name) {
		fRoleMethodName = name;
	}

	public CallinBaseMethodInfo[] getBaseMethodInfos() {
		return fCallinBaseMethodInfos;
	}

	public void setBaseMethods(CallinBaseMethodInfo[] baseMethods) {
		fTargetBaseMethods = baseMethods;
	}

	public void setDeleteRoleMethod(boolean deleteRoleMethod) {
		fDeleteRoleMethod = deleteRoleMethod;
	}

	@Override
	public RefactoringStatus checkInitialConditions(IProgressMonitor monitor) throws CoreException, OperationCanceledException {
		RefactoringStatus status= new RefactoringStatus();
		
		try {
			monitor.beginTask(OTRefactoringMessages.InlineCallinRefactoring_preconditions_progress, 1);
			if (fRoleMethod == null){
				status.merge(RefactoringStatus.createFatalErrorStatus(OTRefactoringMessages.InlineCallinRefactoring_noMethod_error));
			}else if (!fRoleMethod.exists()){
				status.merge(RefactoringStatus.createFatalErrorStatus(NLS.bind(OTRefactoringMessages.InlineCallinRefactoring_inexistentMethod_error, new Object[] { fRoleMethod
						.getElementName() })));
			}else if (fRoleMethod.isBinary()){
				status.merge(RefactoringStatus.createFatalErrorStatus(NLS.bind(OTRefactoringMessages.InlineCallinRefactoring_binaryMethod_error, new Object[] { fRoleMethod
						.getElementName() })));
			}else if (fRoleMethod.isReadOnly()){
				status.merge(RefactoringStatus.createFatalErrorStatus(NLS.bind(OTRefactoringMessages.InlineCallinRefactoring_readOnlyMethod_error, new Object[] { fRoleMethod
						.getElementName() })));
			}else if (!fRoleMethod.getCompilationUnit().isStructureKnown()){
					status.merge(RefactoringStatus.createFatalErrorStatus(NLS.bind(OTRefactoringMessages.InlineCallinRefactoring_compileErrors_error,
							new Object[] { fRoleMethod.getCompilationUnit().getElementName() })));
			} else if (!RefactoringUtil.isRoleMethod(fRoleMethod)) {
				status.merge(RefactoringStatus.createFatalErrorStatus(NLS.bind(OTRefactoringMessages.InlineCallinRefactoring_notInsideRole_error,
						new Object[] { fRoleMethod.getElementName() })));
			}else{ 
					status.merge(initialize(monitor));
			}
		} finally {
			monitor.done();
		}
		return status;
	}	
	
	private RefactoringStatus initialize(IProgressMonitor monitor) {
		RefactoringStatus status = new RefactoringStatus();
		fRoleMethodName = fRoleMethod.getElementName();
		fRoleType = fRoleMethod.getDeclaringType();
		fRoleCUnit = fRoleMethod.getCompilationUnit();

		if (fRootRole == null) {
			fRootRole = RefactoringASTParser.parseWithASTProvider(fRoleCUnit, true, new SubProgressMonitor(monitor, 99));
		}

		fRoleAST = fRootRole.getAST();
		
		try {
			IType baseType = ((IRoleType) OTModelManager.getOTElement(fRoleMethod.getDeclaringType())).getBaseClass();
			if (baseType != null) {
				if (baseType.isBinary()) {
					status.merge(RefactoringStatus.createFatalErrorStatus(NLS.bind(OTRefactoringMessages.InlineCallinRefactoring_binaryBase_error, baseType.getElementName())));
					return status;
				}
				if(baseType.isReadOnly()){
					status.merge(RefactoringStatus.createFatalErrorStatus(NLS.bind(OTRefactoringMessages.InlineCallinRefactoring_readOnlyBase_error, baseType.getElementName())));
					return status;
				}
				fBaseType = baseType;
				fBaseCUnit = baseType.getCompilationUnit();

				if (fRootBase == null) {
					fRootBase = RefactoringASTParser.parseWithASTProvider(fBaseCUnit, true, new SubProgressMonitor(monitor, 99));
				}
				
				fBaseImportRewriter = StubUtility.createImportRewrite(fRootBase, true);
				fBaseAST = fRootBase.getAST();
			} else {
				status.merge(RefactoringStatus.createFatalErrorStatus(OTRefactoringMessages.InlineCallinRefactoring_unboundRole_error));
			}
		} catch (JavaModelException e) {
			status.merge(createCouldNotParseStatus());
		}
		if (status.hasFatalError()) {
			return status;
		}
		
		IMethodMapping[] callinMappings = ((IRoleType) OTModelManager.getOTElement(fRoleType)).getMethodMappings(IRoleType.CALLINS);

		fBoundCallinMappings = new ArrayList<ICallinMapping>();

		for (int i = 0; i < callinMappings.length; i++) {
			if (callinMappings[i].getRoleMethod().equals(fRoleMethod)) {
				fBoundCallinMappings.add((ICallinMapping) callinMappings[i]);
			}
		}

		if (fBoundCallinMappings.size() == 0) {
			status.merge(RefactoringStatus.createFatalErrorStatus(NLS.bind(
					OTRefactoringMessages.InlineCallinRefactoring_unboundMethod_error, new Object[] { fRoleMethod
							.getElementName() })));
		}
		
		List<CallinBaseMethodInfo> infos = new ArrayList<CallinBaseMethodInfo>();

		for (ICallinMapping mapping : fBoundCallinMappings) {
			try {
				for (IMethod method : mapping.getBoundBaseMethods()) {
					infos.add(new CallinBaseMethodInfo(method, mapping));
				}
				fCallinBaseMethodInfos = infos.toArray(new CallinBaseMethodInfo[infos.size()]);
			} catch (JavaModelException e) {
				status.merge(RefactoringStatus.createFatalErrorStatus(OTRefactoringMessages.InlineCallinRefactoring_unparseableMethodMapping_error));
			}
		}
		return status;
	}
	
	@Override
	public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException {
		RefactoringStatus status = new RefactoringStatus();
		
		status.merge(checkBaseMethods());
		
		if (status.hasFatalError()) {
			return status;
		}

		status.merge(generateNewBaseMethodNames());
		
		status.merge(checkRoleMethodName());
		
		status.merge(checkDependenciesToRole(pm));
		
		status.merge(checkRoleMethodReferences(pm));

		return status;
	}

	private RefactoringStatus checkRoleMethodReferences(IProgressMonitor pm) throws CoreException {
		// search all references for the role method
		final Set<SearchMatch> references = new HashSet<SearchMatch>();
		IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
		SearchPattern pattern = SearchPattern.createPattern(fRoleMethod, IJavaSearchConstants.REFERENCES, SearchPattern.R_EXACT_MATCH);
		SearchEngine engine = new SearchEngine();
		engine.search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, scope, new SearchRequestor() {
			@Override
			public void acceptSearchMatch(SearchMatch match) throws CoreException {
				if (match.getAccuracy() == SearchMatch.A_ACCURATE && !match.isInsideDocComment()) {
					references.add(match);
				}
			}
		}, pm);
		
		RefactoringStatus status = new RefactoringStatus();
		
		List<ICallinMapping> inlinedCallins = new ArrayList<ICallinMapping>();
		for (int i = 0; i < fCallinBaseMethodInfos.length; i++) {
			inlinedCallins.add(fCallinBaseMethodInfos[i].getCallinMapping());
		}

		for (SearchMatch match : references) {
			Object element= match.getElement();
			if (element instanceof ICallinMapping) {
				ICallinMapping mapping = (ICallinMapping) element;
				if(mapping.getRoleMethod().equals(fRoleMethod)){
					if(inlinedCallins.contains(mapping)){
						continue;
					}
				} else {
					status.addError(NLS.bind(OTRefactoringMessages.InlineCallinRefactoring_methodBoundByOtherCallin_error, fRoleMethod.getElementName()));
					continue;
				}
			}
			
			if (element instanceof ICalloutMapping) {
				status.addError(NLS.bind(OTRefactoringMessages.InlineCallinRefactoring_methodIsCallout_error, fRoleMethod.getElementName()));
				continue;
			}
			
			if (fDeleteRoleMethod) {
				if (element instanceof IMember) {
					// try to create context informations for the search result
					IMember referencingMember = (IMember) element;
					String msg = NLS.bind(OTRefactoringMessages.InlineCallinRefactoring_methodIsUsedBy_error,
							fRoleMethod.getElementName(), JavaElementLabels.getTextLabel(referencingMember, JavaElementLabels.ALL_FULLY_QUALIFIED));
					status.addError(msg, JavaStatusContext.create(referencingMember));
				} else {
					status.addError(NLS.bind(OTRefactoringMessages.InlineCallinRefactoring_methodIsUsed_error, fRoleMethod.getElementName()));
				}
			}
		}
		return status;
	}

	private RefactoringStatus checkMethodName(String name) {
		RefactoringStatus result = new RefactoringStatus();
	
		if (name == null)
			return RefactoringStatus.createFatalErrorStatus(OTRefactoringMessages.InlineCallinRefactoring_missingNewMethodName_error);
	
		if ("".equals(name)) //$NON-NLS-1$
			return RefactoringStatus.createFatalErrorStatus(OTRefactoringMessages.InlineCallinRefactoring_emptyMethodName_error);
	
		IJavaProject javaProject = this.fRoleType.getJavaProject();
		String sourceLevel= javaProject.getOption(JavaCore.COMPILER_SOURCE, true);
		String complianceLevel= javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true);
		IStatus status = JavaConventions.validateMethodName(name, sourceLevel, complianceLevel);
		if (status.isOK())
			return result;
	
		switch (status.getSeverity()) {
		case IStatus.ERROR:
			return RefactoringStatus.createFatalErrorStatus(status.getMessage());
		case IStatus.WARNING:
			return RefactoringStatus.createWarningStatus(status.getMessage());
		case IStatus.INFO:
			return RefactoringStatus.createInfoStatus(status.getMessage());
		default: // no nothing
			return new RefactoringStatus();
		}
	}

	private RefactoringStatus checkIfMethodExists() {
		try {
			if (methodWithNameExists(fBaseType, fRoleMethodName)){
				return RefactoringStatus.createErrorStatus(NLS.bind(OTRefactoringMessages.InlineCallinRefactoring_methodNameClash_error, fRoleMethodName));
			}
		} catch (JavaModelException exception) {
			return createCouldNotParseStatus();
		}
		return new RefactoringStatus();
	}

	private RefactoringStatus checkDependenciesToRole(IProgressMonitor pm) throws JavaModelException {
		RefactoringStatus status = new RefactoringStatus();

		IMethod[] referencedMethods = ReferenceFinderUtil.getMethodsReferencedIn(new IJavaElement[] { fRoleMethod }, null /* owner */, new SubProgressMonitor(pm,
				1));
		for (int i = 0; i < referencedMethods.length; i++) {
			IMethod referencedMethod = referencedMethods[i];
			if (referencedMethod.getDeclaringType().equals(fRoleType)) {
				status.merge(RefactoringStatus.createErrorStatus(NLS.bind(OTRefactoringMessages.InlineCallinRefactoring_methodUsesRoleMethod_error,
						fRoleMethodName, referencedMethod)));
			}
		}

		IField[] referencedFileds = ReferenceFinderUtil.getFieldsReferencedIn(new IJavaElement[] { fRoleMethod }, null /* owner */, new SubProgressMonitor(pm,
				1));
		for (int i = 0; i < referencedFileds.length; i++) {
			IField referencedFiled = referencedFileds[i];
			if (referencedFiled.getDeclaringType().equals(fRoleType)) {
				status.merge(RefactoringStatus.createErrorStatus(NLS.bind(OTRefactoringMessages.InlineCallinRefactoring_methodUsesRoleField_error,
						fRoleMethodName, referencedFiled)));
			}
		}
		return status;
	}
	
	RefactoringStatus checkRoleMethodName() {
		RefactoringStatus status = new RefactoringStatus();
		status.merge(checkIfMethodExists());
		status.merge(checkMethodName(fRoleMethodName));
		return status;
	}

	RefactoringStatus checkBaseMethods() {
		RefactoringStatus status = new RefactoringStatus();
		if (fTargetBaseMethods == null || fTargetBaseMethods.length == 0) {
			status.merge(RefactoringStatus.createFatalErrorStatus(OTRefactoringMessages.InlineCallinRefactoring_missingBaseMethod_error));
		}
		return status;
	}

	private boolean methodWithNameExists(IType type, String methodName) throws JavaModelException {
		IMethod[] methods = type.getMethods();
		for (IMethod method : methods) {
			if (method.getElementName().equals(methodName))
				return true;
		}
		return false;
	}

	private RefactoringStatus createCouldNotParseStatus() {
		return RefactoringStatus.createFatalErrorStatus(OTRefactoringMessages.InlineCallinRefactoring_unparseableType_error);
	}

	@Override
	public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException {
		pm.beginTask(OTRefactoringMessages.InlineCallinRefactoring_creatingChange_progress, fCallinBaseMethodInfos.length + 2);
		inlineCallin(pm);
		Change change = new CompositeChange(getName(), new TextFileChange[] { fBaseTextFileChange, fRoleTextFileChange });
		pm.done();
		return change;
	}

	private void inlineCallin(IProgressMonitor pm) throws CoreException {
		fBaseRewrite = ASTRewrite.create(fBaseAST);
		fRoleRewrite = ASTRewrite.create(fRoleAST);
		
		for (int i = 0; i < fTargetBaseMethods.length; i++) {

			IMethod baseMethod = fTargetBaseMethods[i].getMethod();
			CallinBaseMethodInfo methodInfo = fTargetBaseMethods[i];
			renameBaseMethod(methodInfo);
			MethodDeclaration wrapperMethodDeclaration = createWrapperMethod(methodInfo);
			Statement roleMethodInvocation = createRoleMethodInvocation(methodInfo);
			List<Statement> statements = wrapperMethodDeclaration.getBody().statements();

			// change the strategy for the different mapping kinds
			switch (methodInfo.getCallinMapping().getCallinKind()) {
			case ICallinMapping.KIND_BEFORE:
				statements.add(0, roleMethodInvocation);
				break;
			case ICallinMapping.KIND_AFTER:
				// TODO check for result parameter mappings
				if (!baseMethod.getReturnType().equals(Character.toString(Signature.C_VOID))) {
					// remove the base method invocation
					statements.clear();
		
					// insert local variable statement to save the return value
					// of
					// the base method invocation
					MethodDeclaration baseMethodDeclaration = RefactoringUtil.methodToDeclaration(baseMethod, fRootBase);
					String varName = generateResultVarName(methodInfo);
					VariableDeclarationFragment fragment = fBaseAST.newVariableDeclarationFragment();
					fragment.setName(fBaseAST.newSimpleName(varName));
					fragment.setInitializer(createBaseMethodInvocation(methodInfo));
					VariableDeclarationStatement variableDeclarationStatement = fBaseAST.newVariableDeclarationStatement(fragment);
					variableDeclarationStatement.setType((Type) ASTNode.copySubtree(fBaseAST, baseMethodDeclaration.getReturnType2()));
					statements.add(variableDeclarationStatement);

					// invoke the role method
					statements.add(roleMethodInvocation);

					// return the stored return value
					ReturnStatement returnStatement = fBaseAST.newReturnStatement();
					returnStatement.setExpression(fBaseAST.newSimpleName(varName));
					statements.add(returnStatement);
				} else {
					statements.add(roleMethodInvocation);
				}
				break;
			case ICallinMapping.KIND_REPLACE:
				statements.clear();
				statements.add(roleMethodInvocation);
				break;
			default:
				break;
			}
		
			insertMethodIntoBase(wrapperMethodDeclaration, baseMethod);
			pm.worked(1);
		}
		
		adjustMethodMappings();
		pm.worked(1);
		
		copyRoleMethodToBase(fTargetBaseMethods[0]);
		pm.worked(1);
		
		if (fDeleteRoleMethod) {
			deleteRoleMethod();
		}
		
		// create the text change for the base
		MultiTextEdit baseMultiEdit = new MultiTextEdit();
		baseMultiEdit.addChild(fBaseRewrite.rewriteAST());
		fBaseTextFileChange = new TextFileChange(fBaseCUnit.getElementName(), (IFile) fBaseCUnit.getResource());
		fBaseTextFileChange.setTextType("java"); //$NON-NLS-1$
		fBaseTextFileChange.setEdit(baseMultiEdit);
			
		if (fBaseImportRewriter.hasRecordedChanges()) {
			TextEdit edit = fBaseImportRewriter.rewriteImports(null);
			baseMultiEdit.addChild(edit);
			fBaseTextFileChange.addTextEditGroup(new TextEditGroup(OTRefactoringMessages.OTRefactoring_organizeImports_editName, new TextEdit[] { edit }));
		}

		// create the text change for the role
		MultiTextEdit roleMultiEdit = new MultiTextEdit();
		roleMultiEdit.addChild(fRoleRewrite.rewriteAST());
		fRoleTextFileChange = new TextFileChange(fRoleCUnit.getElementName(), (IFile) fRoleCUnit.getResource());
		fRoleTextFileChange.setTextType("java"); //$NON-NLS-1$
		fRoleTextFileChange.setEdit(roleMultiEdit);
	}

	
	/**
	 * Renames the given base method to the name given in the info object.
	 * 
	 * @param baseMethodInfo
	 *            the info object containing the base method and the new base
	 *            method name
	 * @throws JavaModelException
	 */
	private void renameBaseMethod(CallinBaseMethodInfo baseMethodInfo) throws JavaModelException {
		ASTNode baseMethodDeclaration = RefactoringUtil.methodToDeclaration(baseMethodInfo.getMethod(), fRootBase);
		fBaseRewrite.set(baseMethodDeclaration, MethodDeclaration.NAME_PROPERTY, fBaseAST.newSimpleName(baseMethodInfo.getNewMethodName()), null);
	}

	/**
	 * Creates the method declaration for the wrapper method with the old base
	 * method name.
	 * 
	 * @param baseMethodInfo
	 *            the info object containing the base method and the new base
	 *            method name
	 * @return the generated wrapper method declaration
	 * @throws CoreException
	 */
	private MethodDeclaration createWrapperMethod(CallinBaseMethodInfo baseMethodInfo) throws CoreException {
		MethodDeclaration baseMethodDeclaration = RefactoringUtil.methodToDeclaration(baseMethodInfo.getMethod(), fRootBase);
		MethodDeclaration methodDeclaration = (MethodDeclaration) ASTNode.copySubtree(fBaseAST, baseMethodDeclaration);
		methodDeclaration.setBody(createMethodBody(baseMethodInfo));
		return methodDeclaration;
	}

	/**
	 * Creates the method body for the wrapper method that maps the inlined
	 * method binding.
	 * 
	 * @param baseMethodInfo
	 *            the info object containing the base method and the new base
	 *            method name
	 * @return the method body
	 * @throws JavaModelException
	 */
	private Block createMethodBody(CallinBaseMethodInfo baseMethodInfo) throws JavaModelException {
		Block block = fBaseAST.newBlock();
		List<Statement> statements = block.statements();
		MethodInvocation invocation = createBaseMethodInvocation(baseMethodInfo);
		
		// create a return statement for the base method invocation if necessary
		MethodDeclaration declaration = RefactoringUtil.methodToDeclaration(baseMethodInfo.getMethod(), fRootBase);
		final Type type = declaration.getReturnType2();
		if (type == null || (type instanceof PrimitiveType && PrimitiveType.VOID.equals(((PrimitiveType) type).getPrimitiveTypeCode()))) {
			statements.add(invocation.getAST().newExpressionStatement(invocation));
		} else {
			ReturnStatement statement = invocation.getAST().newReturnStatement();
			statement.setExpression(invocation);
			statements.add(statement);
		}
		return block;
	}

	/**
	 * Removes the base methods from the inlined method mappings. If all bound
	 * base methods of a binding are removed, the whole mapping will be deleted.
	 * The change is performed on the given <code>ASTRewrite</code>.
	 * 
	 * @param rewrite
	 *            the rewrite that notes the changes
	 * @throws JavaModelException
	 */
	private void adjustMethodMappings() throws JavaModelException {
	
		// create a map that gathers multiple methods for the same callin mapping
		Map<IMethod, ICallinMapping> methodToMapping = new HashMap<IMethod, ICallinMapping>();
		for (int i = 0; i < fTargetBaseMethods.length; i++) {
			methodToMapping.put(fTargetBaseMethods[i].getMethod(), fTargetBaseMethods[i].getCallinMapping());
		}
	
		for (ICallinMapping callinMapping : methodToMapping.values()) {
			Collection<IMethod> baseMethodsToRemove = methodToMapping.keySet();
			
			// search the current callin mapping in the ast
			CallinMappingDeclaration methodMappingDecl = (CallinMappingDeclaration) RefactoringUtil.methodMappingToDeclaration(callinMapping, fRootRole);
			
			if (baseMethodsToRemove.containsAll(Arrays.asList(callinMapping.getBoundBaseMethods()))) {
				// if all bound base methods should be removed the remove the
				// method mapping
				fRoleRewrite.remove(methodMappingDecl, null);
				
			} else {
				// otherwise remove the references to the base methods from the
				// mapping
				CallinMappingDeclaration mappingDeclaration = methodMappingDecl;
				List<MethodSpec> baseMethods = mappingDeclaration.getBaseMappingElements();
				for (MethodSpec methodSpec : baseMethods) {
					for (IMethod method : baseMethodsToRemove) {
						IMethodBinding methodBinding = methodSpec.resolveBinding();
						IMethod boundMethod = (IMethod) methodBinding.getJavaElement();
						if (method.equals(boundMethod)) {
							// TODO remove unused imports
							fRoleRewrite.remove(methodSpec, null);
						}
					}
				}
			}
		}
	}

	private void deleteRoleMethod() throws JavaModelException {
		// TODO remove unused imports
		AbstractTypeDeclaration declaration = (AbstractTypeDeclaration) RefactoringUtil.typeToDeclaration(fRoleType, fRootRole);
		ChildListPropertyDescriptor descriptor = typeToBodyDeclarationProperty(fBaseType, fRootBase);
		MethodDeclaration roleMethodDecl = RefactoringUtil.methodToDeclaration(fRoleMethod, fRootRole);
		fRoleRewrite.getListRewrite(declaration, descriptor).remove(roleMethodDecl, null);
	}

	private boolean hasResultTunneling(CallinBaseMethodInfo baseMethodInfo) throws JavaModelException {
		// only replace callins can have result tunneling
		if (baseMethodInfo.getCallinMapping().getCallinKind() != ICallinMapping.KIND_REPLACE) {
			return false;
		}

		// only base methods with return types can produce result tunneling
		if (isVoidMethod(baseMethodInfo.getMethod())) {
			return false;
		}
		
		// only role methods without a return type can produce result tunneling
		if (!isVoidMethod(fRoleMethod)) {
			return false;
		}

		if (hasResultParameterMapping(baseMethodInfo.getCallinMapping())) {
			return false;
		}
		
		return true;
	}


	private boolean hasResultParameterMapping(ICallinMapping callinMapping) throws JavaModelException {
		if (!hasParameterMapping(callinMapping)) {
			return false;
		}
		AbstractMethodMappingDeclaration mappingDecl = RefactoringUtil.methodMappingToDeclaration(callinMapping, fRootRole);
		List<ParameterMapping> parameterMappings = mappingDecl.getParameterMappings();
		for (ParameterMapping parameterMapping : parameterMappings) {
			if (parameterMapping.hasResultFlag()) {
				return true;
			}
		}
		return false;
	}

	private Statement createRoleMethodInvocation(CallinBaseMethodInfo baseMethodInfo) throws JavaModelException {
		MethodInvocation invocation = fBaseAST.newMethodInvocation();
		ICallinMapping callinMapping = baseMethodInfo.getCallinMapping();

		invocation.setName(fBaseAST.newSimpleName(fRoleMethodName));

		CallinMappingDeclaration callinMappingDecl = (CallinMappingDeclaration) RefactoringUtil.methodMappingToDeclaration(callinMapping, fRootRole);
		if (hasParameterMapping(callinMapping)) {
			copyRoleParameterMappingsToInvocation(invocation, callinMappingDecl, baseMethodInfo);
		} else {
			String[] parameterNames = baseMethodInfo.getMethod().getParameterNames();
			int length = callinMapping.getCallinKind() ==  ICallinMapping.KIND_REPLACE 
						? parameterNames.length 
						: this.fRoleMethod.getParameterNames().length;
			copyInvocationParameters(invocation, parameterNames, length);
		}
		if (needsReturnStatement(baseMethodInfo)) {
			ReturnStatement statement = invocation.getAST().newReturnStatement();
			statement.setExpression(invocation);
			return statement;
		} else {
			return invocation.getAST().newExpressionStatement(invocation);
		}
	}
	
	private boolean needsReturnStatement(CallinBaseMethodInfo baseMethodInfo) throws JavaModelException {
		if (isReplace(baseMethodInfo)) {
			return !isVoidMethod(baseMethodInfo.getMethod());
		} else {
			return !(isVoidMethod(fRoleMethod) || isVoidMethod(baseMethodInfo.getMethod()));
		}
	}

	private boolean isVoidMethod(IMethod method) throws JavaModelException {
		return method.getReturnType().equals(Character.toString(Signature.C_VOID));
	}

	private void copyRoleParameterMappingsToInvocation(MethodInvocation invocation, CallinMappingDeclaration callinMappingDecl,
			CallinBaseMethodInfo baseMethodInfo)
			throws JavaModelException {	
		MethodSpec baseMethodSpec = findBaseMethodSpec(callinMappingDecl, baseMethodInfo.getMethod());
		
		List<SingleVariableDeclaration> baseMappingParams = baseMethodSpec.parameters();
		
		// create a map that maps the original param names of the base method to
		// the param names used in the mapping
		Map<String, String> callinParamNamesToBaseMethodParamNames = new HashMap<String, String>();
		String[] names = baseMethodInfo.getMethod().getParameterNames();
		for (int i = 0; i < names.length; i++) {
			callinParamNamesToBaseMethodParamNames.put(baseMappingParams.get(i).getName().getIdentifier(), names[i]);
		}
		
		List<ParameterMapping> paramMappings = callinMappingDecl.getParameterMappings();
		MethodSpec roleMethodSpec = (MethodSpec) callinMappingDecl.getRoleMappingElement();
		List<SingleVariableDeclaration> roleMappingParams = roleMethodSpec.parameters();


		for (SingleVariableDeclaration singleVariableDeclaration : roleMappingParams) {
			String paramName = singleVariableDeclaration.getName().getIdentifier();
			for (ParameterMapping mapping : paramMappings) {
				if (mapping.hasResultFlag())
					continue;
				if (mapping.getIdentifier().getIdentifier().equals(paramName)) {
					Expression expr = (Expression) ASTNode.copySubtree(fBaseAST, mapping.getExpression());
					substituteBaseParams(expr, callinParamNamesToBaseMethodParamNames, baseMethodInfo);
					invocation.arguments().add(expr);
				}
			}
		}

		
		if (isReplace(baseMethodInfo)) {
			Set<String> tunneledParams = findTunneledParameters(baseMethodInfo);
			// replace tunneled parameters in base method invocations
			for (String paramName : tunneledParams) {
				String tunneledName = generateTunneledParamName(paramName);
				invocation.arguments().add(fBaseAST.newSimpleName(tunneledName));
			}
		}
	}
	
	private void copyBaseParameterMappingsToInvocation(MethodInvocation invocation, CallinMappingDeclaration callinMappingDecl,
			CallinBaseMethodInfo baseMethodInfo) throws JavaModelException {
		MethodSpec roleMethodSpec = (MethodSpec) callinMappingDecl.getRoleMappingElement();
		List<SingleVariableDeclaration> roleMappingParams = roleMethodSpec.parameters();

		// create a map that maps the original param names of the role method to
		// the param names used in the mapping
		Map<String, String> callinParamNamesToRoleMethodParamNames = new HashMap<String, String>();
		String[] roleParamNames = fRoleMethod.getParameterNames();
		for (int i = 0; i < roleParamNames.length; i++) {
			callinParamNamesToRoleMethodParamNames.put(roleMappingParams.get(i).getName().getIdentifier(), roleParamNames[i]);
		}

		List<ParameterMapping> paramMappings = callinMappingDecl.getParameterMappings();
		MethodSpec baseMethodSpec = findBaseMethodSpec(callinMappingDecl, baseMethodInfo.getMethod());
		List<SingleVariableDeclaration> baseMappingParams = baseMethodSpec.parameters();

		// create a map that maps the original param names of the base method to
		// the param names used in the mapping
		Map<String, String> callinParamNamesToBaseMethodParamNames = new HashMap<String, String>();
		String[] baseParamNames = baseMethodInfo.getMethod().getParameterNames();
		for (int i = 0; i < baseParamNames.length; i++) {
			callinParamNamesToBaseMethodParamNames.put(baseMappingParams.get(i).getName().getIdentifier(), baseParamNames[i]);
		}
		
		Map<String, Expression> baseParamToExpression = new HashMap<String, Expression>();
		

		for (SingleVariableDeclaration singleVariableDeclaration : baseMappingParams) {
			String paramName = singleVariableDeclaration.getName().getIdentifier();
			for (ParameterMapping mapping : paramMappings) {
				if (mapping.hasResultFlag())
					continue;
				if (mapping.getExpression() instanceof SimpleName) {
					SimpleName mappedName = (SimpleName) mapping.getExpression();
					if (mappedName.getIdentifier().equals(paramName)) {
						// resolve the original param names because param names
						// in the mapping can be different
						String roleMethodIdentifier = callinParamNamesToRoleMethodParamNames.get(mapping.getIdentifier().getIdentifier());
						String baseMethodIdentifier = callinParamNamesToBaseMethodParamNames.get(paramName);
						baseParamToExpression.put(baseMethodIdentifier, fBaseAST.newSimpleName(roleMethodIdentifier));
						// base parameters can only be mapped once �4.4.(b)
						continue;
					}
				}
			}
		}
		
		// pass the right statement for each base param
		for (String name : baseParamNames) {
			if(baseParamToExpression.get(name) == null){
				String tunneledName = generateTunneledParamName(name);
				invocation.arguments().add(fBaseAST.newSimpleName(tunneledName));
			}else{
				// pass the simple name of the mapped role method parameter
				invocation.arguments().add(baseParamToExpression.get(name));
			}
		}

		if (isReplace(baseMethodInfo)) {

			// parameter mappings are handled differently because they depend on
			// the mapping
			if (!hasParameterMapping(baseMethodInfo.getCallinMapping())) {
				// if the role method doesn't declare the same number of
				// parameters
				// as the base method, the parameters have to be appended
				int roleMethodParameterLength = baseMethodInfo.getCallinMapping().getRoleMethod().getParameterNames().length;
				int baseMethodParameterLength = baseMethodInfo.getMethod().getParameterNames().length;
				if (roleMethodParameterLength < baseMethodParameterLength) {
					appendInvocationParameters(invocation, baseMethodInfo.getMethod(), roleMethodParameterLength);
				}
			}
		}
	}
	
	private void substituteBaseParams(Expression expr, Map<String, String> callinParamNamesToBaseMethodParamNames, CallinBaseMethodInfo baseMethodInfo)
			throws JavaModelException {
		ArrayList<String> callinParamNames = new ArrayList<String>();
		for (String name : callinParamNamesToBaseMethodParamNames.keySet()) {
			callinParamNames.add(name);
		}
		SimpleNameFinder simpleNameFinder = new SimpleNameFinder(callinParamNames);
		expr.accept(simpleNameFinder);
		List<SimpleName> simpleNames = simpleNameFinder.getResult();
		for (SimpleName simpleName : simpleNames) {
			String baseMethodParamName = callinParamNamesToBaseMethodParamNames.get(simpleName.getIdentifier());
			simpleName.setIdentifier(baseMethodParamName);
		}
	}

	private Set<String> findTunneledParameters(CallinBaseMethodInfo baseMethodInfo)
			throws JavaModelException {
		// try to reuse cached result
		if (fCachedBaseMethodInfo == baseMethodInfo) {
			return fCachedTunneledParameters;
		}
		fCachedBaseMethodInfo = baseMethodInfo;
		Set<String> tunneledParams = new HashSet<String>();
		CallinMappingDeclaration callinMappingDecl = (CallinMappingDeclaration) RefactoringUtil.methodMappingToDeclaration(baseMethodInfo.getCallinMapping(),
				fRootRole);
		MethodSpec baseMethodSpec = findBaseMethodSpec(callinMappingDecl, baseMethodInfo.getMethod());

		List<SingleVariableDeclaration> baseMappingParams = baseMethodSpec.parameters();

		// create a map that maps the original param names of the base method to
		// the param names used in the mapping
		Map<String, String> baseMethodParamNameToBaseMappingParamName = new HashMap<String, String>();
		String[] names = baseMethodInfo.getMethod().getParameterNames();
		for (int i = 0; i < names.length; i++) {
			baseMethodParamNameToBaseMappingParamName.put(names[i], baseMappingParams.get(i).getName().getIdentifier());
		}

		List<ParameterMapping> paramMappings = callinMappingDecl.getParameterMappings();
		tunneledParams.addAll(Arrays.asList(baseMethodInfo.getMethod().getParameterNames()));
		for (int i = 0; i < names.length; i++) {
			for (ParameterMapping mapping : paramMappings) {
				if (mapping.hasResultFlag())
					continue;
				Expression expr = (Expression) mapping.getExpression();
				if (expr instanceof SimpleName) {
					SimpleName simpleName = (SimpleName) expr;
					if (simpleName.getIdentifier().equals(baseMethodParamNameToBaseMappingParamName.get(names[i]))) {
						tunneledParams.remove(names[i]);
					}
				}
			}
		}
		fCachedTunneledParameters = tunneledParams;
		return fCachedTunneledParameters;
	}
	
	/**
	 * Copies the invocation parameter of the given base method to the given
	 * method invocation.
	 * 
	 * @param invocation
	 *            the method invocation to receive the parameters
	 * @param method
	 *            the method that declares the parameters
	 * @throws JavaModelException
	 */
	private void copyInvocationParameters(MethodInvocation invocation, IMethod method) throws JavaModelException {
		String[] parameterNames = method.getParameterNames();
		copyInvocationParameters(invocation, parameterNames, parameterNames.length);		
	}
	// this variant allows to cut off unneeded parameters (only for before/after callins):
	private void copyInvocationParameters(MethodInvocation invocation, String[] names, int n) throws JavaModelException {
		for (int i=0; i<n; i++)
			invocation.arguments().add(fBaseAST.newSimpleName(names[i]));
	}

	/**
	 * Copies the role method to the base class and creates store variables for
	 * implicit result tunneling. If the role method was a callin method, base
	 * methods are replaced by method invocations to the new method name,
	 * specified in <code>baseMethodInfo</code>.
	 * 
	 * @param rewrite
	 *            the rewrite that notes the changes
	 * @param baseMethodInfo
	 *            the info object containing the base method, callin mapping,
	 *            and the new base method name
	 * @throws JavaModelException
	 */
	private void copyRoleMethodToBase(CallinBaseMethodInfo baseMethodInfo) throws JavaModelException {
		ASTNode roleMethodDeclaration = RefactoringUtil.methodToDeclaration(fRoleMethod, fRootRole);
		MethodDeclaration copyOfRoleMethodDeclaration = (MethodDeclaration) ASTNode.copySubtree(fBaseAST, roleMethodDeclaration);
		copyOfRoleMethodDeclaration.setName(fBaseAST.newSimpleName(fRoleMethodName));
		
		// change the visibility of the copy to private to avoid overriding and
		// hide the role method
		if (!Flags.isPrivate(fRoleMethod.getFlags()) && !Flags.isCallin(fRoleMethod.getFlags()))
			changeToPrivateVisibility(fBaseRewrite, copyOfRoleMethodDeclaration);
		
		// special treatment for replace mappings/callin methods
		if (Flags.isCallin(fRoleMethod.getFlags())) {
			handleCallinMethod(fBaseRewrite, baseMethodInfo, copyOfRoleMethodDeclaration);
		}
		
		if ((isReplace(baseMethodInfo))) {
			if (hasParameterMapping(baseMethodInfo.getCallinMapping())) {
				// append parameters that are tunneled because of a missing
				// parameter mapping �4.4.(b)
				appendTunneledParameterDeclarations(baseMethodInfo, copyOfRoleMethodDeclaration);
			} else {
				// if a callin method doesn't declare the same number of
				// parameters
				// as the base method, the parameters have to be appended
				int roleMethodParameterLength = baseMethodInfo.getCallinMapping().getRoleMethod().getParameterNames().length;
				int baseMethodParameterLength = baseMethodInfo.getMethod().getParameterNames().length;
				if (roleMethodParameterLength < baseMethodParameterLength) {
					appendParameterDeclarations(copyOfRoleMethodDeclaration, baseMethodInfo.getMethod(), roleMethodParameterLength);
				}
			}
		}
		
		findAndReplaceCallouts(fBaseRewrite, copyOfRoleMethodDeclaration);
		
		insertMethodIntoBase(copyOfRoleMethodDeclaration, baseMethodInfo.getMethod());
		
		// oragnize imports
		Set<IBinding> staticImports = new HashSet<IBinding>();
		Set<ITypeBinding> imports = new HashSet<ITypeBinding>();
		ImportRewriteUtil.collectImports(fRoleMethod.getJavaProject(), roleMethodDeclaration, imports, staticImports, false);
		for (ITypeBinding typeBinding : imports) {
			fBaseImportRewriter.addImport(typeBinding);
		}
		for (IBinding binding : staticImports) {
			fBaseImportRewriter.addStaticImport(binding);
		}
	}

	/**
	 * Replaces <code>public</code> and <code>protected</code> by a
	 * <code>private</code> modifier. If the method has default visibility
	 * <code>private</code> modifier will be prepended to the modifier list.
	 * 
	 * @param rewrite
	 *            the rewrite that notes the changes
	 * @param methodDeclaration
	 *            the method declaration to be changed
	 */
	private void changeToPrivateVisibility(ASTRewrite astRewrite, MethodDeclaration methodDeclaration) {
		Modifier privateVisibility = methodDeclaration.getAST().newModifier(ModifierKeyword.PRIVATE_KEYWORD);
		
		List<IExtendedModifier> modifiers = methodDeclaration.modifiers();
		for (IExtendedModifier extendedModifier : modifiers) {
			if (extendedModifier instanceof Modifier) {
				Modifier modifier = (Modifier) extendedModifier;
				if (Modifier.isPublic(modifier.getKeyword().toFlagValue())) {
					astRewrite.replace(modifier, privateVisibility, null);
					return;
				}
				if (Modifier.isProtected(modifier.getKeyword().toFlagValue())) {
					astRewrite.replace(modifier, privateVisibility, null);
					return;
				}
				if (Modifier.isPrivate(modifier.getKeyword().toFlagValue())) {
					// don't replace private modifiers or create a 2nd private
					// modifier
					return;
				}
			}
		}
		// no visibility modifier was found => default visibility will be
		// reduced to private
		astRewrite.getListRewrite(methodDeclaration, MethodDeclaration.MODIFIERS2_PROPERTY).insertFirst(privateVisibility, null);
	}

	/**
	 * Handles special cases for callin methods like result tunneling and base
	 * call replacement.
	 * 
	 * @param rewrite
	 *            the rewrite that notes the changes
	 * @param baseMethodInfo
	 *            the info object containing the base method, callin mapping,
	 *            and the new base method name
	 * @param methodDeclaration
	 *            the method declaration node of the role method
	 * @throws JavaModelException
	 */
	private void handleCallinMethod(ASTRewrite astRewrite, CallinBaseMethodInfo baseMethodInfo, MethodDeclaration methodDeclaration)
			throws JavaModelException {
		List<Statement> statements = methodDeclaration.getBody().statements();
		removeCallinFlag(methodDeclaration);
		
		if (fRoleMethod.getReturnType().equals(Character.toString(Signature.C_VOID))) {
			ReturnFinder returnFinder = new ReturnFinder();
			methodDeclaration.accept(returnFinder);
			List<ReturnStatement> returns = returnFinder.getResult();
			for (ReturnStatement returnStatement : returns) {
				astRewrite.replace(returnStatement, fBaseAST.newReturnStatement(), null);
			}
		}
		
		if (hasResultTunneling(baseMethodInfo)) {
			String varName = generateResultVarName(baseMethodInfo);
			VariableDeclarationFragment fragment = fBaseAST.newVariableDeclarationFragment();
			fragment.setName(fBaseAST.newSimpleName(varName));
			VariableDeclarationStatement variableDeclarationStatement = fBaseAST.newVariableDeclarationStatement(fragment);
			MethodDeclaration baseMethodDeclaration = RefactoringUtil.methodToDeclaration(baseMethodInfo.getMethod(), fRootBase);
			variableDeclarationStatement.setType((Type) ASTNode.copySubtree(fBaseAST, baseMethodDeclaration.getReturnType2()));
			statements.add(0, variableDeclarationStatement);
			
			
			// return the stored return value
			ReturnStatement returnStatement = fBaseAST.newReturnStatement();
			returnStatement.setExpression(fBaseAST.newSimpleName(varName));
			statements.add(returnStatement);
			
			substituteBaseCalls(methodDeclaration, astRewrite, varName, baseMethodInfo);
			
		} else if(hasResultParameterMapping(baseMethodInfo.getCallinMapping())
				&& isVoidMethod(fRoleMethod)) {
			// replace callins may define a result mapping if they don't have a
			// return value
			AbstractMethodMappingDeclaration mappingDecl = RefactoringUtil.methodMappingToDeclaration(baseMethodInfo.getCallinMapping(), fRootRole);
			List<ParameterMapping> parameterMappings = mappingDecl.getParameterMappings();
			Expression resultMappingExpression = null;
			for (ParameterMapping parameterMapping : parameterMappings) {
				if (parameterMapping.hasResultFlag()) {
					resultMappingExpression = (Expression) parameterMapping.getExpression();
				}
			}

			// return the mapped return value
			ReturnStatement returnStatement = fBaseAST.newReturnStatement();
			returnStatement.setExpression((Expression) ASTNode.copySubtree(fBaseAST, resultMappingExpression));
			statements.add(returnStatement);
			substituteBaseCalls(methodDeclaration, astRewrite, null /* localStoreVarIdentifier */, baseMethodInfo);
		} else {
			substituteBaseCalls(methodDeclaration, astRewrite, null /* localStoreVarIdentifier */, baseMethodInfo);
		}
	
		Modifier privateVisibility = fBaseAST.newModifier(ModifierKeyword.PRIVATE_KEYWORD);
		methodDeclaration.modifiers().add(privateVisibility);
	
		// callin methods need the same return type as the base method
		// after inlining
		MethodDeclaration declaration = RefactoringUtil.methodToDeclaration(baseMethodInfo.getMethod(), fRootBase);
		methodDeclaration.setReturnType2((Type) ASTNode.copySubtree(fBaseAST, declaration.getReturnType2()));
	}

	/**
	 * Removes a callin modifier from the given <code>MethodDeclaration</code>.
	 * 
	 * @param methodDeclaration
	 *            the method declaration to remove the callin modifier from
	 * @return true if a callin modifier was removed - otherwise false
	 */
	private boolean removeCallinFlag(MethodDeclaration methodDeclaration) {
		List<IExtendedModifier> modifiers = methodDeclaration.modifiers();
	
		for (IExtendedModifier extendedModifier : modifiers) {
			if (extendedModifier instanceof Modifier) {
				Modifier modifier = (Modifier) extendedModifier;
				if (Modifier.isCallin(modifier.getKeyword().toFlagValue())) {
					modifier.delete();
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Substitutes base calls in the body of a callin method by method
	 * invocations to the method specified in baseMethodInfo. If a identifier
	 * for a local variable is given, the method invocations will be assigned to
	 * it.
	 * 
	 * @param methodDeclaration
	 *            the method declaration containing the base calls
	 * @param rewrite
	 *            the rewrite that notes the changes
	 * @param localStoreVarIdentifier
	 *            the name of a return store variable - <code>null</code> if no
	 *            return value must be stored
	 * @param baseMethodInfo
	 *            the info object containing the base method and the new base
	 *            method name
	 * @throws JavaModelException
	 */
	private void substituteBaseCalls(MethodDeclaration methodDeclaration, ASTRewrite astRewrite, String localStoreVarIdentifier,
			CallinBaseMethodInfo baseMethodInfo)
			throws JavaModelException {
		BaseCallFinder baseCallFinder = new BaseCallFinder();
		methodDeclaration.accept(baseCallFinder);
		BaseCallMessageSend[] baseCalls = baseCallFinder.getResult();
		
		if (localStoreVarIdentifier != null) {
			// create assignment statements if a store identifier exist
			for (int i = 0; i < baseCalls.length; i++) {
				BaseCallMessageSend basecall = baseCalls[i];
	
				Assignment assignment = fBaseAST.newAssignment();
				assignment.setLeftHandSide(fBaseAST.newSimpleName(localStoreVarIdentifier));
				assignment.setRightHandSide(createBaseMethodInvocation(baseMethodInfo));
	
				astRewrite.replace(basecall, assignment, null);
			}
		} else {
			// substitute the base calls with a simple base call
			for (int i = 0; i < baseCalls.length; i++) {
				BaseCallMessageSend basecall = baseCalls[i];
				astRewrite.replace(basecall, createBaseMethodInvocation(baseMethodInfo), null);
			}
		}
	}

	private void findAndReplaceCallouts(ASTRewrite astRewrite, MethodDeclaration copyOfRoleMethodDeclaration) throws JavaModelException {
		MethodInvocationFinder methodInvocationFinder = new MethodInvocationFinder();
		copyOfRoleMethodDeclaration.accept(methodInvocationFinder);
		List<MethodInvocation> methodInvocations = methodInvocationFinder.getResult();
		IMethodMapping[] calloutMappings = ((IRoleType) OTModelManager.getOTElement(fRoleType)).getMethodMappings(IRoleType.CALLOUTS);
	
		Map<String, IMethodMapping> calloutNameToMapping = new HashMap<String, IMethodMapping>();
		for (IMethodMapping methodMapping : calloutMappings) {
			if(methodMapping instanceof ICalloutMapping){
				ICalloutMapping calloutMapping = (ICalloutMapping)methodMapping;
				calloutNameToMapping.put(calloutMapping.getRoleMethodHandle().getSelector(), calloutMapping);
				
			}
			if(methodMapping instanceof ICalloutToFieldMapping){
				ICalloutToFieldMapping calloutToFieldMapping = (ICalloutToFieldMapping)methodMapping;
				calloutNameToMapping.put(calloutToFieldMapping.getRoleMethodHandle().getSelector(), calloutToFieldMapping);
			}
		}
		
		for (MethodInvocation invocation : methodInvocations) {
			IMethodMapping mapping = calloutNameToMapping.get(invocation.getName().getIdentifier());
			if(mapping == null){
				continue;
			}
			// TODO Parameter mappings
			switch (mapping.getMappingKind()) {
			case IOTJavaElement.CALLOUT_MAPPING:
				ICalloutMapping calloutMapping = (ICalloutMapping)mapping;
				invocation.setName(fBaseAST.newSimpleName(calloutMapping.getBoundBaseMethod().getElementName()));
				break;
			case IOTJavaElement.CALLOUT_TO_FIELD_MAPPING:
				ICalloutToFieldMapping calloutToFieldMapping = (ICalloutToFieldMapping)mapping;
				CalloutMappingDeclaration calloutDecl = (CalloutMappingDeclaration) RefactoringUtil.methodMappingToDeclaration(calloutToFieldMapping, fRootRole);
				String fieldName = calloutToFieldMapping.getBoundBaseField().getElementName();
				if (Modifier.isSet(calloutDecl.bindingOperator().getBindingModifier())) {
					// set
					Assignment setAssignment = fBaseAST.newAssignment();
					setAssignment.setLeftHandSide(fBaseAST.newSimpleName(fieldName));
					Expression setExpression = (Expression) ASTNode.copySubtree(fBaseAST, (Expression) invocation.arguments().get(0));
					setAssignment.setRightHandSide(setExpression);
					astRewrite.replace(invocation, setAssignment, null);
				} else {
					// get
					astRewrite.replace(invocation, fBaseAST.newSimpleName(fieldName), null);
				}
				
				
				break;
			default:
				break;
			}
		}
	}

	private MethodInvocation createBaseMethodInvocation(CallinBaseMethodInfo baseMethodInfo) throws JavaModelException {
		MethodInvocation invocation = fBaseAST.newMethodInvocation();
		invocation.setName(fBaseAST.newSimpleName(baseMethodInfo.getNewMethodName()));
		
		
		if (isReplace(baseMethodInfo)) {	
			// parameter mappings are handled differently because they depend on
			// the mapping
			if (!hasParameterMapping(baseMethodInfo.getCallinMapping())) {
				// replace callins call the method within the role method body
				copyInvocationParameters(invocation, baseMethodInfo.getCallinMapping().getRoleMethod());
				// if the role method doesn't declare the same number of
				// parameters as the base method, the parameters have to be
				// appended
				int roleMethodParameterLength = baseMethodInfo.getCallinMapping().getRoleMethod().getParameterNames().length;
				int baseMethodParameterLength = baseMethodInfo.getMethod().getParameterNames().length;
				if (roleMethodParameterLength < baseMethodParameterLength) {
					appendInvocationParameters(invocation, baseMethodInfo.getMethod(), roleMethodParameterLength);
				}
			} else {
				CallinMappingDeclaration callinMappingDecl = (CallinMappingDeclaration) RefactoringUtil.methodMappingToDeclaration(baseMethodInfo
						.getCallinMapping(), fRootRole);
				copyBaseParameterMappingsToInvocation(invocation, callinMappingDecl, baseMethodInfo);
			}
		} else {
			// replace and after callins call the base method within the wrapper
			// method of the role
			copyInvocationParameters(invocation, baseMethodInfo.getMethod());
		}


		return invocation;
	}

	private boolean isReplace(CallinBaseMethodInfo baseMethodInfo) {
		return baseMethodInfo.getCallinMapping().getCallinKind() == ICallinMapping.KIND_REPLACE;
	}
	
	private boolean hasParameterMapping(IMethodMapping mapping) throws JavaModelException {
		AbstractMethodMappingDeclaration decl = RefactoringUtil.methodMappingToDeclaration(mapping, fRootRole);
		return decl.hasParameterMapping();
	}

	private void insertMethodIntoBase(MethodDeclaration methodDeclaration, IMethod baseMethod) throws JavaModelException {
		AbstractTypeDeclaration declaration = (AbstractTypeDeclaration) RefactoringUtil.typeToDeclaration(fBaseType, fRootBase);
		ChildListPropertyDescriptor descriptor = typeToBodyDeclarationProperty(fBaseType, fRootBase);
		MethodDeclaration baseMethodDeclaration = RefactoringUtil.methodToDeclaration(baseMethod, fRootBase);
		fBaseRewrite.getListRewrite(declaration, descriptor).insertBefore(methodDeclaration, baseMethodDeclaration, null);
	}
	


	/**
	 * Appends the parameter declarations from the given <code>baseMethod</code>
	 * to the end of the parameter list of the given
	 * <code>roleMethodDeclaration</code>, starting at the given
	 * <code>offset</code>. This method is used if the role method declares
	 * fewer parameters than the base method.
	 * 
	 * @param roleMethodDeclaration
	 *            the method declaration of the copied role method
	 * @param baseMethod
	 *            the base method to copy the parameter declarations from
	 * @param offset
	 *            the offset to start
	 * @throws JavaModelException
	 */
	private void appendParameterDeclarations(MethodDeclaration roleMethodDeclaration, IMethod baseMethod, int offset) throws JavaModelException {
		MethodDeclaration baseMethodDecl = RefactoringUtil.methodToDeclaration(baseMethod, fRootBase);
		List<SingleVariableDeclaration> baseParamDeclarations = baseMethodDecl.parameters();
		for (int i = offset; i < baseParamDeclarations.size(); i++) {
			SingleVariableDeclaration paramDecl = (SingleVariableDeclaration) ASTNode.copySubtree(fBaseAST, baseParamDeclarations.get(i));
			
			// generate a parameter name that does not produce a name clash
			List<String> localVarNames = new ArrayList<String>();
			localVarNames.addAll(localVarNamesInRoleMethod());
			localVarNames.addAll(Arrays.asList(fRoleMethod.getParameterNames()));
			String validParameterName = generateVarName(paramDecl.getName().getIdentifier(), localVarNames);
			paramDecl.setName(fBaseAST.newSimpleName(validParameterName));
			fBaseRewrite.getListRewrite(roleMethodDeclaration, MethodDeclaration.PARAMETERS_PROPERTY).insertLast(paramDecl, null);
		}
	}

	private void appendTunneledParameterDeclarations(CallinBaseMethodInfo baseMethodInfo, MethodDeclaration copyOfRoleMethodDeclaration)
			throws JavaModelException {
		// append tunneled parameters to roleMethodSignature
		Set<String> tunneledParams = findTunneledParameters(baseMethodInfo);
		// replace tunneled parameters in base method invocations
		MethodDeclaration baseMethodDecl = RefactoringUtil.methodToDeclaration(baseMethodInfo.getMethod(), fRootBase);
		List<SingleVariableDeclaration> baseParamDeclarations = baseMethodDecl.parameters();
		ListRewrite listRewrite = fBaseRewrite.getListRewrite(copyOfRoleMethodDeclaration, MethodDeclaration.PARAMETERS_PROPERTY);
		for (SingleVariableDeclaration varDecl : baseParamDeclarations) {
			String paramName = varDecl.getName().getIdentifier();
			if (tunneledParams.contains(paramName)) {
				String tunneledName = generateTunneledParamName(paramName);
				SingleVariableDeclaration paramDecl = (SingleVariableDeclaration) ASTNode.copySubtree(fBaseAST, varDecl);
				paramDecl.setName(fBaseAST.newSimpleName(tunneledName));
				listRewrite.insertLast(paramDecl, null);
			}
		}
	}

	/**
	 * Appends invocation parameter names from the given method from the given
	 * offset. This method is used to extend base method calls if the role
	 * method declares fewer parameters than the base method.
	 * 
	 * @param invocation
	 *            the method invocation to receive the parameters
	 * @param method
	 *            the method that declares the parameters
	 * @param offset
	 *            the offset to begin to copy
	 * @throws JavaModelException
	 */
	private void appendInvocationParameters(MethodInvocation invocation, IMethod method, int offset) throws JavaModelException {
		String[] names = method.getParameterNames();
		
		for (int i = offset; i < names.length; i++) {
			String name = names[i];

			// generate a valid parameter name to prevent name clashes
			List<String> localVarNames = new ArrayList<String>();
			localVarNames.addAll(localVarNamesInRoleMethod());
			localVarNames.addAll(Arrays.asList(fRoleMethod.getParameterNames()));
			String validParameterName = generateVarName(name, localVarNames);
			invocation.arguments().add(fBaseAST.newSimpleName(validParameterName));
		}
	}

	private RefactoringStatus generateNewBaseMethodNames() {
		try {
			generateBaseMethodNames(fTargetBaseMethods);
		} catch (JavaModelException e) {
			return createCouldNotParseStatus();
		}
		return new RefactoringStatus();
	}

	private String generateResultVarName(CallinBaseMethodInfo baseMethodInfo) throws JavaModelException {
		String name = "baseResult"; //$NON-NLS-1$
		List<String> paramNames = Arrays.asList(baseMethodInfo.getMethod().getParameterNames());
		return generateVarName(name, paramNames);
	}

	/**
	 * Generates a name for a parameter or local variable that does not produce
	 * name clashes with a base field, a parameter name or a local variable
	 * name. If there are no name clashes, the method returns the desired name,
	 * otherwise it returns the desired name with an appended number.
	 * 
	 * @param desiredName
	 *            the name to be checked
	 * @param localVarNames
	 *            list of local variable names
	 * @return a name that does not produce a name clash
	 */
	private String generateVarName(String desiredName, List<String> localVarNames) {
		String varName = desiredName;
		
		int i = 2;
		while (fBaseType.getField(varName).exists() || localVarNames.contains(varName)) {
			varName = desiredName + i;
			i++;
		}
		return varName;
	}

	private void generateBaseMethodNames(CallinBaseMethodInfo[] baseMethodInfos) throws JavaModelException {
		for (int i = 0; i < baseMethodInfos.length; i++) {
			String newBaseName = "base_" + fTargetBaseMethods[i].getMethod().getElementName(); //$NON-NLS-1$
			int j = 2;
			while (methodWithNameExists(fBaseType, newBaseName)) {
				newBaseName = "base_" + fTargetBaseMethods[i].getMethod().getElementName() + j; //$NON-NLS-1$
				j++;
			}
			baseMethodInfos[i].setNewMethodName(newBaseName);
		}
	}

	private String generateTunneledParamName(String identifier) throws JavaModelException {
		String upperCasedName = identifier.substring(0, 1).toUpperCase() + identifier.substring(1);
		List<String> localVarNames = new ArrayList<String>();
		localVarNames.addAll(localVarNamesInRoleMethod());
		localVarNames.addAll(Arrays.asList(fRoleMethod.getParameterNames()));
		String tunneledName = generateVarName("tunneled" + upperCasedName, localVarNames); //$NON-NLS-1$
		return tunneledName;
	}

	private List<String> localVarNamesInRoleMethod() throws JavaModelException {
		List<String> localVars = new ArrayList<String>();
		MethodDeclaration declaration = RefactoringUtil.methodToDeclaration(fRoleMethod, fRootRole);
		LocalVariableFinder localVariableFinder = new LocalVariableFinder();
		declaration.accept(localVariableFinder);
		localVars = localVariableFinder.getResult();
		return localVars;
	}

	private MethodSpec findBaseMethodSpec(CallinMappingDeclaration callinMappingDecl, IMethod baseMethod) {
		MethodSpec baseMethodSpec = null;
		List<MethodSpec> methodSpecs = callinMappingDecl.getBaseMappingElements();
		for (MethodSpec methodSpec : methodSpecs) {
			IMethodBinding methodBinding = methodSpec.resolveBinding();
			IMethod method = (IMethod) methodBinding.getJavaElement();
			if (method.equals(baseMethod)) {
				baseMethodSpec = methodSpec;
			}
		}
		return baseMethodSpec;
	}

	private ChildListPropertyDescriptor typeToBodyDeclarationProperty(IType type, CompilationUnit node) throws JavaModelException {
		ASTNode result = RefactoringUtil.typeToDeclaration(type, node);
		if (result instanceof AbstractTypeDeclaration)
			return ((AbstractTypeDeclaration) result).getBodyDeclarationsProperty();
		else if (result instanceof AnonymousClassDeclaration)
			return AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY;
	
		Assert.isTrue(false);
		return null;
	}

	private class LocalVariableFinder extends ASTVisitor {
	
		private List<String> _locals = new ArrayList<String>();
	
		@Override
		public boolean visit(VariableDeclarationFragment node) {
			_locals.add(node.getName().getIdentifier());
			return false;
		}
	
		public List<String> getResult() {
			return _locals;
		}
	}

	private class SimpleNameFinder extends ASTVisitor {
	
		private List<SimpleName> _simpleNames = new ArrayList<SimpleName>();
		private List<String> _identifier;
	
		public SimpleNameFinder(List<String> identifier) {
			_identifier = identifier;
		}
	
		@Override
		public boolean visit(SimpleName node) {
			if (_identifier.contains(node.getIdentifier())) {
				_simpleNames.add(node);
			}
			return false;
		}
	
		public List<SimpleName> getResult() {
			return _simpleNames;
		}
	}

	private class MethodInvocationFinder extends ASTVisitor {
	
		private List<MethodInvocation> _methodInvocations = new ArrayList<MethodInvocation>();
	
		@Override
		public boolean visit(MethodInvocation node) {
			_methodInvocations.add(node);
			return false;
		}
	
		public List<MethodInvocation> getResult() {
			return _methodInvocations;
		}
	}

	private class ReturnFinder extends ASTVisitor {
	
		private List<ReturnStatement> _returns = new ArrayList<ReturnStatement>();
	
		@Override
		public boolean visit(ReturnStatement node) {
			_returns.add(node);
			return false;
		}
	
		public List<ReturnStatement> getResult() {
			return _returns;
		}
	}
}