/**********************************************************************
 * This file is part of "Object Teams Development Tooling"-Software
 * 
 * Copyright 2010, 2012 Johannes Gebauer 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
 * 
 * Please visit http://www.objectteams.org for updates and contact.
 * 
 * Contributors:
 *		Johannes Gebauer - Initial API and implementation
 *		Stephan Herrmann - Bug fixes and improvements
 **********************************************************************/
package org.eclipse.objectteams.otdt.internal.refactoring.adaptor.pullup;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
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.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.*;
import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.MethodDeclarationMatch;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchParticipant;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.SearchRequestor;
import org.eclipse.jdt.internal.core.search.matching.MethodPattern;
import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.BodyDeclarationRewrite;
import org.eclipse.jdt.internal.corext.refactoring.Checks;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
import org.eclipse.jdt.internal.corext.refactoring.util.JavaStatusContext;
import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
import org.eclipse.jdt.internal.corext.refactoring.structure.ImportRewriteUtil;
import org.eclipse.jdt.internal.corext.refactoring.structure.MemberVisibilityAdjustor.IncomingMemberVisibilityAdjustment;
import org.eclipse.jdt.internal.corext.refactoring.structure.TypeVariableMaplet;
import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompilationUnitRange;
import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.JdtFlags;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.internal.corext.util.SearchUtils;
import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider;
import org.eclipse.jdt.ui.JavaElementLabels;
import org.eclipse.ltk.core.refactoring.GroupCategorySet;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry;
import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
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.IOTType;
import org.eclipse.objectteams.otdt.core.IRoleType;
import org.eclipse.objectteams.otdt.core.OTModelManager;
import org.eclipse.objectteams.otdt.core.TypeHelper;
import org.eclipse.objectteams.otdt.core.hierarchy.OTTypeHierarchies;
import org.eclipse.objectteams.otdt.internal.core.AbstractCalloutMapping;
import org.eclipse.objectteams.otdt.internal.core.CalloutMapping;
import org.eclipse.objectteams.otdt.internal.core.CalloutToFieldMapping;
import org.eclipse.objectteams.otdt.internal.core.RoleType;
import org.eclipse.objectteams.otdt.internal.refactoring.RefactoringMessages;
import org.eclipse.objectteams.otdt.internal.refactoring.util.IAmbuguityMessageCreator;
import org.eclipse.objectteams.otdt.internal.refactoring.util.IOverloadingMessageCreator;
import org.eclipse.objectteams.otdt.internal.refactoring.util.RefactoringUtil;
import org.eclipse.osgi.util.NLS;
import org.eclipse.text.edits.TextEditGroup;

import base org.eclipse.jdt.internal.core.search.BasicSearchEngine;
import base org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
import base org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
import base org.eclipse.jdt.internal.corext.refactoring.structure.HierarchyProcessor;
import base org.eclipse.jdt.internal.corext.refactoring.structure.MemberVisibilityAdjustor;
import base org.eclipse.jdt.internal.corext.refactoring.structure.PullUpRefactoringProcessor;
import base org.eclipse.jdt.internal.corext.refactoring.structure.ReferenceFinderUtil;
import base org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeRefactoringProcessor;
import base org.eclipse.jdt.internal.ui.refactoring.PullUpMemberPage;
import base org.eclipse.jdt.internal.ui.refactoring.PullUpMemberPage.MemberActionInfo;

/**
 * @author Johannes Gebauer
 * 
 */
@SuppressWarnings({ "restriction", "decapsulation" }) // private base classes
public team class PullUpAdaptor {
	
	protected team class PullUpRefactoringProcessorRole playedBy PullUpRefactoringProcessor {
		

		public ChangeManagerDetails changeManagerDetails; // set when this team is activated (see #createChangeManager())


		// callout (constant):
		GroupCategorySet getSET_PULL_UP() -> get GroupCategorySet SET_PULL_UP;
		// callouts (fields):
		void setFCachedSkippedSuperTypes(Set<IType> fCachedSkippedSuperTypes) 
																-> set Set<IType> fCachedSkippedSuperTypes;
		Set<IType> getFCachedSkippedSuperTypes() 				-> get Set<IType> fCachedSkippedSuperTypes;
		IMember[] getMembersToDelete(IProgressMonitor monitor) 	-> IMember[] getMembersToDelete(IProgressMonitor monitor);
		IMethod[] getFDeletedMethods() 							-> get IMethod[] fDeletedMethods;
		IMember[] getFMembersToMove() 							-> get IMember[] fMembersToMove;

		// callouts (methods):
		IType getDestinationType() 								-> IType getDestinationType();
		IMember[] getMembersToMove() 							-> IMember[] getMembersToMove();
		IType getDeclaringType() 								-> IType getDeclaringType();
		ITypeHierarchy getDestinationTypeHierarchy(IProgressMonitor pm)
																-> ITypeHierarchy getDestinationTypeHierarchy(IProgressMonitor pm);
		IMember[] getCreatedDestinationMembers() 				-> IMember[] getCreatedDestinationMembers();
		void addMatchingMember(Map<IMember, Set<IMember>> mapping, IMember key, IMember matchingMember)
			-> void addMatchingMember(Map<IMember, Set<IMember>> mapping, IMember key, IMember matchingMember);
		
		private void checkFinalConditions(IProgressMonitor pm, CheckConditionsContext context, RefactoringStatus status) throws CoreException {
			
			status.merge(checkForAspectBindings(pm));
			status.merge(checkOverloadingAndAmbiguity(pm));
			status.merge(checkOverriding(pm));
			if(TypeHelper.isRole(getDeclaringType().getFlags())){
				status.merge(checkDestinationForOTElements(pm));
				status.merge(checkShadowingFieldInImplicitHierarchy(pm));
			}
		}
		
		void checkFinalConditions(IProgressMonitor pm, CheckConditionsContext context, RefactoringStatus status) <- after RefactoringStatus checkFinalConditions(IProgressMonitor pm,
				CheckConditionsContext context) with {
			pm <- pm,
			context <- context,
			status <- result
		}

		private RefactoringStatus checkShadowingFieldInImplicitHierarchy(IProgressMonitor pm) throws JavaModelException {
			RefactoringStatus status = new RefactoringStatus();
			if(!TypeHelper.isRole(getDestinationType().getFlags())){
				return status;
			}
			
			ITypeHierarchy hier = getDestinationTypeHierarchy(pm);
			ArrayList<IType> implicitSubRoles = new ArrayList<IType>();
			implicitSubRoles.addAll(Arrays.asList(OTTypeHierarchies.getInstance().getAllTSubTypes(hier, getDestinationType())));
			
			// remove the subtypes of the declaring type
			implicitSubRoles.removeAll(Arrays.asList(OTTypeHierarchies.getInstance().getAllTSubTypes(hier, getDeclaringType())));
			
			pm.beginTask(RefactoringMessages.PullUpAdaptor_checkShadowing_progress, implicitSubRoles.size());
			pm.subTask(""); //$NON-NLS-1$
			
			for (int i = 0; i < getFMembersToMove().length; i++) {
				IMember element = getFMembersToMove()[i];
				if(element instanceof IField){
					IField field = (IField) element;
					for (IType type : implicitSubRoles) {
						IField shadowingField = RefactoringUtil.fieldIsShadowedInType(field.getElementName(), field.getTypeSignature(), type);
						if(shadowingField != null){
							
							ArrayList<IMember> membersToDelete = new ArrayList<IMember>();
							membersToDelete.addAll(Arrays.asList(getMembersToDelete(pm)));
							// do not indicate shadowing by deleted fields as an error
							if(!membersToDelete.contains(shadowingField)) {
								String msg = NLS.bind(RefactoringMessages.PullUpAdaptor_fieldShadowing_error, 
													  field.getElementName(), 
													  type.getFullyQualifiedName('.'));
								status.addFatalError(msg, JavaStatusContext.create(shadowingField));
							}
							
						}
						pm.worked(1);
						// do not repeat errors in hierarchy
						if(status.hasFatalError()){
							pm.done();
							return status;
						}
					}
				}
			}
			pm.done();
			return status;
			
		}
		
		private RefactoringStatus checkDestinationForOTElements(IProgressMonitor pm) throws JavaModelException {
			RefactoringStatus status = new RefactoringStatus();
			for (int i = 0; i < getFMembersToMove().length; i++) {
				IMember element = getFMembersToMove()[i];
				if (element instanceof IMethod){
					IMethod method = (IMethod)element;
					// callin methods can only be moved to roles
					if(Flags.isCallin(method.getFlags()) && !TypeHelper.isRole(getDestinationType().getFlags())){
						String msg = NLS.bind(RefactoringMessages.PullUpAdaptor_callinMethodToNonRole_error, method.getElementName());
						status.addFatalError(msg, JavaStatusContext.create(method));
					} else {
						// for callout bindings check if the base member will be accessible after refactoring:
						checkDestinationForCallout(method, getDestinationType(), status, pm);
					}
				}
			}
			return status;
		}
		
		protected static void checkDestinationForCallout(IMethod method, IType destinationType, RefactoringStatus status, IProgressMonitor pm) throws JavaModelException {
			IMember baseMember = null;
			switch (method.getElementType()) {
			case IOTJavaElement.CALLOUT_MAPPING:
				baseMember = ((CalloutMapping)method).getBoundBaseMethod();
				break;
			case IOTJavaElement.CALLOUT_TO_FIELD_MAPPING:
				baseMember = ((CalloutToFieldMapping)method).getBoundBaseField();
				break;
			}
			if (baseMember == null) return; // not a callout or unresolvable base member
			IType requiredBaseType = baseMember.getDeclaringType();
			if (!TypeHelper.isRole(destinationType.getFlags())) {
				String msg = NLS.bind(RefactoringMessages.PullUpAdaptor_calloutToNonRole_error, method.getElementName());
				status.addFatalError(msg, JavaStatusContext.create(method));
			} else {
				IRoleType roleType = (IRoleType) OTModelManager.getOTElement(destinationType);
				IType baseClass = roleType.getBaseClass();
				if (baseClass == null) {
					String msg = NLS.bind(RefactoringMessages.PullUpAdaptor_calloutToUnboundRole_error, method.getElementName());
					status.addFatalError(msg, JavaStatusContext.create(method));									
				} else if (!requiredBaseType.equals(baseClass)) {
					IJavaElement[] elements = new IJavaElement[]{requiredBaseType, baseClass};
					ASTParser astParser = ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL);
					astParser.setProject(method.getDeclaringType().getJavaProject());
					IBinding[] bindings = astParser.createBindings(elements, pm);
					ITypeBinding requiredBaseBinding = (ITypeBinding)bindings[0];
					ITypeBinding baseOfDestination = (ITypeBinding)bindings[1];
					if (!baseOfDestination.isAssignmentCompatible(requiredBaseBinding)) {
						String msg = NLS.bind(RefactoringMessages.PullUpAdaptor_calloutBaseNotBoundInDest_error, 
												new Object[]{method.getElementName(), destinationType.getElementName(), baseMember.getElementName()});
						status.addFatalError(msg, JavaStatusContext.create(method));											
					}
				}
			}
		}

		private RefactoringStatus checkOverloadingAndAmbiguityInType(IProgressMonitor pm, IType type) throws JavaModelException {
			RefactoringStatus status = new RefactoringStatus();
			ITypeHierarchy hier = getDestinationTypeHierarchy(pm);
			for (int i = 0; i < getFMembersToMove().length; i++) {
				IMember element = getFMembersToMove()[i];
				if (element instanceof IMethod){
					final IMethod method = (IMethod)element;
					String[] paramTypes = method.getParameterTypes();
					status.merge(RefactoringUtil.checkOverloadingAndAmbiguity(type, hier, method.getElementName(), paramTypes,
							new IAmbuguityMessageCreator() {

						public String createAmbiguousMethodSpecifierMsg() {
							return RefactoringMessages.PullUpAdaptor_ambiguousMethodSpec_error;
						}

					}, new IOverloadingMessageCreator() {

						public String createOverloadingMessage() {
							String msg = NLS.bind(RefactoringMessages.PullUpAdaptor_overloading_error, method.getElementName());
							return msg;
						}

					}, pm));
				}
			}
			return status;
		}
		
		private RefactoringStatus checkOverloadingAndAmbiguity(IProgressMonitor pm) throws JavaModelException {
			
			ITypeHierarchy destinationTypeHierarchy = getDestinationTypeHierarchy(pm);
			IType[] subtypes = destinationTypeHierarchy.getAllSubtypes(getDestinationType());
			
			pm.beginTask(RefactoringMessages.PullUpAdaptor_checkOverloading_progress, subtypes.length + 1);
			pm.subTask(""); //$NON-NLS-1$
			
			RefactoringStatus status = new RefactoringStatus();
			
			// check overloading in destination type
			status.merge(checkOverloadingAndAmbiguityInType(pm, getDestinationType()));
			
			pm.worked(1);
			
			// do not repeat errors in hierarchy
			if(status.hasFatalError()){
				pm.done();
				return status;
			}
			
			// check overloading in subtypes of the destination type
			for (int i = 0; i < subtypes.length; i++) {
				status.merge(checkOverloadingAndAmbiguityInType(pm, subtypes[i]));
				
				pm.worked(1);
				
				// do not repeat errors in hierarchy
				if(status.hasFatalError()){
					pm.done();
					return status;
				}
			}
			pm.done();
			return status;
		}
		
		private RefactoringStatus checkOverriding(IProgressMonitor pm) throws JavaModelException{
			RefactoringStatus status = new RefactoringStatus();
			
			ITypeHierarchy hier = getDestinationTypeHierarchy(pm);
			ArrayList<IType> allSubTypes = new ArrayList<IType>();
			allSubTypes.addAll(Arrays.asList(hier.getAllSubtypes(getDestinationType())));
			
			// remove the subtypes of the declaring type
			allSubTypes.removeAll(Arrays.asList(hier.getAllSubtypes(getDeclaringType())));
			
			pm.beginTask(RefactoringMessages.PullUpAdaptor_checkOverriding_progress, allSubTypes.size());
			pm.subTask(""); //$NON-NLS-1$
			
			for (int i = 0; i < getFMembersToMove().length; i++) {
				IMember element = getFMembersToMove()[i];
				if(element instanceof IMethod){
					IMethod method = (IMethod) element;
					for (IType type : allSubTypes) {
						IMethod overridingMethod = methodIsOverriddenInType(method.getElementName(), method.getParameterTypes(), type);
						if(overridingMethod != null){
							
							ArrayList<IMember> membersToMove = new ArrayList<IMember>();
							membersToMove.addAll(Arrays.asList(getMembersToMove()));
							ArrayList<IMember> membersToDelete = new ArrayList<IMember>();
							membersToDelete.addAll(Arrays.asList(getMembersToDelete(pm)));
							// do not indicate overriding for deleted/moved methods as an error
							if(!membersToMove.contains(overridingMethod) && !membersToDelete.contains(overridingMethod)) {
								String msg = NLS.bind(RefactoringMessages.PullUpAdaptor_overriding_error,
													  method.getElementName(),
													  type.getFullyQualifiedName('.'));
								status.addError(msg, JavaStatusContext.create(overridingMethod));
							}
							
						}
						pm.worked(1);
						// do not repeat errors in hierarchy
						if(status.hasError()){
							pm.done();
							return status;
						}
					}
				}
			}
			pm.done();
			return status;
		}
		
		private IMethod methodIsOverriddenInType(String methodName, String[] paramTypes, IType type){
			IMethod method = type.getMethod(methodName, paramTypes);
			if(method.exists()){
				return method;
			}
			return null;
		}
		
		
		/**
		 * Searches for aspect bindings that reference members to be moved.
		 * @return The refactoring status contains warnings if any referencing aspect bindings exist.
		 */
		private RefactoringStatus checkForAspectBindings(IProgressMonitor monitor) throws CoreException {
			// search all references for the members to be moved
			IMember[] membersToMove = getMembersToMove();
			final HashMap<IMember,Set<SearchMatch>> references= new HashMap<IMember,Set<SearchMatch>>();
			IJavaSearchScope scope= SearchEngine.createWorkspaceScope();
			for (int i = 0; i < membersToMove.length; i++) {
				final IMember member = membersToMove[i];
				// may not be able to access return type, but IGNORE_RETURN_TYPE is only effective with ALL_OCCURRENCES:
				int limitTo = IJavaSearchConstants.ALL_OCCURRENCES|IJavaSearchConstants.IGNORE_RETURN_TYPE;
				SearchPattern pattern= SearchPattern.createPattern(member, limitTo, SearchPattern.R_EXACT_MATCH);
				SearchEngine engine= new SearchEngine();
				engine.search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant()}, scope, new SearchRequestor() {
					public void acceptSearchMatch(SearchMatch match) throws CoreException {
						if (   match.getAccuracy() == SearchMatch.A_ACCURATE
							&& !match.isInsideDocComment()
							&& !(match instanceof MethodDeclarationMatch)) // limit to references despite ALL_OCCURRENCES above:
						{
							if(references.get(member) == null){
								Set<SearchMatch> refSet = new HashSet<SearchMatch>();
								refSet.add(match);
								references.put(member, refSet);
							}else{
								references.get(member).add(match);
							}
						}
					}
				}, monitor);
			}
			
			// search the matches for aspect bindings
			RefactoringStatus status = new RefactoringStatus();
			for (int i = 0; i < membersToMove.length; i++) {
				IMember member = membersToMove[i];
				Set<SearchMatch> refSet = references.get(member);
				if(refSet == null){
					continue;
				}
				for (SearchMatch match : refSet) {
					Object element= match.getElement();
					if (element instanceof ICalloutMapping) {
						ICalloutMapping mapping = (ICalloutMapping) element;
						IMethod boundBaseMethod = mapping.getBoundBaseMethod();
						if (boundBaseMethod == null) {
							addUnresolvedBaseMemberError(mapping, status, member);
						} else if(boundBaseMethod.equals(member)){
							addAspectBindingWarning(member, status, mapping);
						}
					}
					if (element instanceof ICalloutToFieldMapping) {
						ICalloutToFieldMapping mapping = (ICalloutToFieldMapping) element;
						IField boundBaseField = mapping.getBoundBaseField();
						if (boundBaseField == null) {
							addUnresolvedBaseMemberError(mapping, status, member);
						} else if(boundBaseField.equals(member)){
							addAspectBindingWarning(member, status, mapping);
						}
					}
					if (element instanceof ICallinMapping) {
						ICallinMapping mapping = (ICallinMapping) element;
						for (int j = 0; j < mapping.getBoundBaseMethods().length; j++) {
							if(mapping.getBoundBaseMethods()[i].equals(member)){
								addAspectBindingWarning(member, status, mapping);
								break;
							}
						}
					}	
				}
			}
			return status;
		}
		
		private void addUnresolvedBaseMemberError(IMethodMapping referencedMapping, RefactoringStatus status, IMember member) 
		{
			status.addEntry(new RefactoringStatusEntry(RefactoringStatus.ERROR,
					NLS.bind(RefactoringMessages.PullUpAdaptor_referencedCalloutUnresolvedBaseMember_error,
							 referencedMapping.getElementName(),
							 member.getElementName())));
		}

		/**
		 * Adds a warning to the given refactoring status that notifies the user about existing aspect bingings.
		 * 
		 * @param member the member to be pulled up.
		 * @param status the refactoring status, where the warning should be added.
		 * @param mapping the method mapping that causes the warning.
		 */
		private void addAspectBindingWarning(IMember member, RefactoringStatus status,IMethodMapping mapping){
			status.addEntry(new RefactoringStatusEntry(RefactoringStatus.WARNING,
					NLS.bind(RefactoringMessages.PullUpAdaptor_referencedByMethodBinding_error,
							 member.getElementName(), 
							 mapping.getDeclaringType().getFullyQualifiedName())));
		
		}
		
		/**
		 * Adds implicit role super types for roles. Candidate types are the possible super types,
		 * that are available as the destination type.
		 */
		callin IType[] getCandidateTypes(final RefactoringStatus status, final IProgressMonitor monitor) throws JavaModelException{
			RefactoringStatus jdtStatus = new RefactoringStatus();
			IType[] jdtCandidates = base.getCandidateTypes(jdtStatus, monitor);
			final IType declaring= getDeclaringType();
			// try to get the corresponding OTType that is represented in the declaring type
			IOTType otType = OTModelManager.getOTElement(declaring);
			if(otType != null && otType instanceof RoleType){
				RoleType role = (RoleType) otType;
				IType[] otSuperTypes = role.newTypeHierarchy(monitor).getAllSupertypes(declaring);
				List<IType> list = new ArrayList<IType>();
				int binary = 0;
				for (int i = 0; i < otSuperTypes.length; i++) {
					IType type = otSuperTypes[i];
					if(OTModelManager.hasOTElementFor(otSuperTypes[i])){
						IOTType otSuperType = OTModelManager.getOTElement(type);
						if(otSuperType instanceof RoleType && type != null && type.exists() && !type.isReadOnly() && !type.isBinary()){
							list.add(type);
						}else if(type.isBinary()){
							binary += 1;
						}
					}
				}
				if(!list.isEmpty()){
					if(jdtStatus.hasFatalError()){
						if (otSuperTypes.length == binary)
							status.addFatalError(RefactoringCoreMessages.PullUPRefactoring_no_all_binary);
					}else{
						status.merge(jdtStatus);
					}
					Collections.reverse(list);
					list.addAll(0,Arrays.asList(jdtCandidates));
					return list.toArray(new IType[list.size()]);
				}
			}
			status.merge(jdtStatus);
			return jdtCandidates;
		}

		getCandidateTypes <- replace getCandidateTypes;
		
		
		
		/**
		 * Prevents callin methods from visibility adjustments.
		 */
		callin boolean needsVisibilityAdjustment(final IMember member, final boolean references, final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException {
			boolean result = base.needsVisibilityAdjustment(member, references, monitor, status);
			if(Flags.isCallin(member.getFlags())){
				return false;
			}else{
				return result;
			}
		}
		
		needsVisibilityAdjustment <- replace needsVisibilityAdjustment;

		void createAbstractMethod(IMethod sourceMethod, CompilationUnitRewrite sourceRewriter, CompilationUnit declaringCuNode, AbstractTypeDeclaration destination, TypeVariableMaplet[] mapping, CompilationUnitRewrite targetRewrite, Map<IMember, IncomingMemberVisibilityAdjustment> adjustments, IProgressMonitor monitor, RefactoringStatus status)
		<- replace void createAbstractMethod(IMethod sourceMethod, CompilationUnitRewrite sourceRewriter, CompilationUnit declaringCuNode, AbstractTypeDeclaration destination, TypeVariableMaplet[] mapping, CompilationUnitRewrite targetRewrite, Map<IMember, IncomingMemberVisibilityAdjustment> adjustments, IProgressMonitor monitor, RefactoringStatus status)
			base when (sourceMethod instanceof IMethodMapping);

		/** support creation of an abstract method from a callout mapping. */
		@SuppressWarnings({ "inferredcallout", "basecall" })
		callin void createAbstractMethod(IMethod sourceMethod, CompilationUnitRewrite sourceRewriter, CompilationUnit declaringCuNode, AbstractTypeDeclaration destination, TypeVariableMaplet[] mapping, CompilationUnitRewrite targetRewrite, Map<IMember, IncomingMemberVisibilityAdjustment> adjustments, IProgressMonitor monitor, RefactoringStatus status)
				throws JavaModelException 
		{
			// search callout decl, not method decl:
			final CalloutMappingDeclaration oldCallout= getCalloutDeclarationNode(sourceMethod, declaringCuNode);
			if (JavaModelUtil.is50OrHigher(sourceMethod.getJavaProject()) && (fSettings.overrideAnnotation || JavaCore.ERROR.equals(sourceMethod.getJavaProject().getOption(JavaCore.COMPILER_PB_MISSING_OVERRIDE_ANNOTATION, true)))) {
				final MarkerAnnotation annotation= sourceRewriter.getAST().newMarkerAnnotation();
				annotation.setTypeName(sourceRewriter.getAST().newSimpleName("Override")); //$NON-NLS-1$
				sourceRewriter.getASTRewrite().getListRewrite(oldCallout, CalloutMappingDeclaration.MODIFIERS2_PROPERTY).insertFirst(annotation, sourceRewriter.createCategorizedGroupDescription(RefactoringCoreMessages.PullUpRefactoring_add_override_annotation, SET_PULL_UP));
			}
			final MethodDeclaration newMethod= targetRewrite.getAST().newMethodDeclaration();
			newMethod.setBody(null);
			newMethod.setConstructor(false);
// callout has no extra dimensions:
//			newMethod.setExtraDimensions(oldCallout.getExtraDimensions());
			newMethod.setJavadoc(null);
			int modifiers= getModifiersWithUpdatedVisibility(sourceMethod, Modifier.ABSTRACT | JdtFlags.clearFlag(Modifier.NATIVE | Modifier.FINAL, sourceMethod.getFlags()), adjustments, monitor, false, status);
// callout doesn't support varargs syntax:
//			if (oldCallout.isVarargs())
//				modifiers&= ~Flags.AccVarargs;
			newMethod.modifiers().addAll(ASTNodeFactory.newModifiers(targetRewrite.getAST(), modifiers));
			newMethod.setName(((SimpleName) ASTNode.copySubtree(targetRewrite.getAST(), oldCallout.getRoleMappingElement().getName())));
			copyReturnType(targetRewrite.getASTRewrite(), getDeclaringType().getCompilationUnit(), (MethodSpec)oldCallout.getRoleMappingElement(), newMethod, mapping);
			copyParameters(targetRewrite.getASTRewrite(), getDeclaringType().getCompilationUnit(), (MethodSpec)oldCallout.getRoleMappingElement(), newMethod, mapping);
// callout does not declare exceptions:
//			copyThrownExceptions(oldCallout, newMethod);
			ImportRewriteContext context= new ContextSensitiveImportRewriteContext(destination, targetRewrite.getImportRewrite());
			ImportRewriteUtil.addImports(targetRewrite, context, newMethod, new HashMap<Name, String>(), new HashMap<Name, String>(), false);
			targetRewrite.getASTRewrite().getListRewrite(destination, destination.getBodyDeclarationsProperty()).insertAt(newMethod, BodyDeclarationRewrite.getInsertionIndex(newMethod, destination.bodyDeclarations()), targetRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.PullUpRefactoring_add_abstract_method, SET_PULL_UP));
		}

		createChangeManager <- replace createChangeManager;
		@SuppressWarnings("inferredcallout")
		callin void createChangeManager(IProgressMonitor monitor, RefactoringStatus status) throws CoreException {
			IType destinationType = getDestinationType();
			IType declaringType = getDeclaringType();
			this.changeManagerDetails = new ChangeManagerDetails(getCompilationUnitRewrite(fCompilationUnitRewrites, declaringType.getCompilationUnit()),
																 getCompilationUnitRewrite(fCompilationUnitRewrites, destinationType.getCompilationUnit()),
																 declaringType,
																 destinationType, 
																 status,
																 monitor);
			within (this)
				base.createChangeManager(monitor, status);
		}

		void getMatchingCalloutsMapping(IType initial, Map<IMember, Set<IMember>> map) 
		<- after Map<IMember, Set<IMember>> getMatchingMembersMapping(IType initial)
				with { initial <- initial, map <- result }

		private void getMatchingCalloutsMapping(IType initial, Map<IMember, Set<IMember>> map) throws JavaModelException {
			final IMember[] members= getCreatedDestinationMembers();
			for (int i= 0; i < members.length; i++) {
				final IMember member= members[i];
				if (member instanceof IMethodMapping && !(member instanceof ICallinMapping)) {
					IMethodMapping mapping = (IMethodMapping) member;
					final IMethod found= findCalloutMethod((IMethod) mapping.getCorrespondingJavaElement(), initial);
					if (found != null)
						addMatchingMember(map, mapping, found);
				}
			}			
		}
		private IMethod findCalloutMethod(IMethod roleMethod, IType initial) throws JavaModelException {
			if (roleMethod == null) return null;
			IOTType otType = OTModelManager.getOTElement(initial);
			if (otType != null && otType.isRole()) {
				IRoleType roleType = (IRoleType) otType;
				String name = roleMethod.getElementName();
				String[] paramTypes = roleMethod.getParameterTypes();
				for (IMethodMapping mapping : roleType.getMethodMappings(IMethodMapping.CALLOUT_MAPPING|IMethodMapping.CALLOUT_TO_FIELD_MAPPING)) {
					if (JavaModelUtil.isSameMethodSignature(name, paramTypes, false, (IMethod) mapping.getCorrespondingJavaElement()))
						return (IMethod) mapping;
				}
			}
			return null;
		}

		/** during createChangeManager we add callouts to the declaration nodes to be removed. */
		protected class HierarchyProcRole playedBy HierarchyProcessor {
			// Note: when defined in role PullUpRefactoringProcessorRole this currently triggers a VerifyError
			
			// === for removal of old callout declarations: ===
			List<ASTNode> getDeclarationNodes(CompilationUnit cuNode, List<IMember> members) 
			<- replace  List<ASTNode> getDeclarationNodes(CompilationUnit cuNode, List<IMember> members);
				
			static callin List<ASTNode> getDeclarationNodes(CompilationUnit cuNode, List<IMember> members)
					throws JavaModelException 
			{
				List<ASTNode> result = base.getDeclarationNodes(cuNode, members);
				for (IMember member : members) {
					ASTNode node= null;
					if (member instanceof AbstractCalloutMapping)
						node= getCalloutDeclarationNode((IMethod) member, cuNode);
					if (node != null)
						result.add(node);
				}
				return result;
			}
		}

		/** during createChangeManager we intercept the visibility adjustments: */
		protected class Adjustor playedBy MemberVisibilityAdjustor {
			setAdjustments <- after setAdjustments;

			private void setAdjustments(Map<IMember, IncomingMemberVisibilityAdjustment> map) {
				PullUpRefactoringProcessorRole.this.changeManagerDetails.adjustments = map;
			}
		}

		/** during createChangeManager we hook into getMethodDeclarationNode to handle callouts, too: */
		protected class CalloutUtil playedBy ASTNodeSearchUtil {
			getMethodDeclarationNode <- replace getMethodDeclarationNode
				base when (!PullUpRefactoringProcessorRole.this.isExecutingCallin());  // inhibit callin trigger during getDeclarationNodes()

			@SuppressWarnings("basecall")
			static callin MethodDeclaration getMethodDeclarationNode(IMethod iMethod, CompilationUnit compilationUnit) throws JavaModelException {
				if (iMethod instanceof AbstractCalloutMapping) {
					// cf block inside org.eclipse.jdt.internal.corext.refactoring.structure.PullUpRefactoringProcessor.createChangeManager()
					// which starts "} else if (member instanceof IMethod) {":
					CalloutMappingDeclaration oldCallout = getCalloutDeclarationNode(iMethod, compilationUnit);
					if (oldCallout != null) {
						CompilationUnitRewrite sourceRewriter = PullUpRefactoringProcessorRole.this.changeManagerDetails.sourceRewrite;
						CompilationUnitRewrite rewrite = PullUpRefactoringProcessorRole.this.changeManagerDetails.rewrite;
						AbstractTypeDeclaration declaration = PullUpRefactoringProcessorRole.this.changeManagerDetails.declaration;
						ImportRewriteContext context = PullUpRefactoringProcessorRole.this.changeManagerDetails.context;
						RefactoringStatus status = PullUpRefactoringProcessorRole.this.changeManagerDetails.status;
						TypeVariableMaplet[] mapping = PullUpRefactoringProcessorRole.this.changeManagerDetails.mapping;
						Map<IMember, IncomingMemberVisibilityAdjustment> adjustments = PullUpRefactoringProcessorRole.this.changeManagerDetails.adjustments;
						ASTRewrite rewriter = rewrite.getASTRewrite();
						IProgressMonitor subsub = PullUpRefactoringProcessorRole.this.changeManagerDetails.monitor;
						
						if (JdtFlags.isStatic(iMethod) && getDestinationType().isInterface())
							status.merge(RefactoringStatus.createErrorStatus(Messages.format(RefactoringCoreMessages.PullUpRefactoring_moving_static_method_to_interface, new String[] { JavaElementLabels.getTextLabel(iMethod, JavaElementLabels.ALL_FULLY_QUALIFIED)}), JavaStatusContext.create(iMethod)));
						CalloutMappingDeclaration newMethod= createNewCalloutDeclarationNode(sourceRewriter, rewrite, iMethod, oldCallout, mapping, adjustments, new SubProgressMonitor(subsub, 1), status);
						rewriter.getListRewrite(declaration, declaration.getBodyDeclarationsProperty()).insertAt(newMethod, BodyDeclarationRewrite.getInsertionIndex(newMethod, declaration.bodyDeclarations()), rewrite.createCategorizedGroupDescription(RefactoringCoreMessages.HierarchyRefactoring_add_member, getSET_PULL_UP()));
						ImportRewriteUtil.addImports(rewrite, context, oldCallout, new HashMap<Name, String>(), new HashMap<Name, String>(), false);

					}
					return null;
				}
				return base.getMethodDeclarationNode(iMethod, compilationUnit);
			}
		}
		
		// ==== COPY&PASTE from base class, use MethodSpec as a template rather then MethodDeclaration: ====
		
		@SuppressWarnings("inferredcallout")
		protected void copyReturnType(ASTRewrite rewrite, ICompilationUnit unit, MethodSpec oldMethod, IMethodNode newMethod, TypeVariableMaplet[] mapping) throws JavaModelException {
			Type newReturnType= null;
			if (mapping.length > 0)
				newReturnType= createPlaceholderForType(oldMethod.getReturnType2(), unit, mapping, rewrite);
			else
				newReturnType= createPlaceholderForType(oldMethod.getReturnType2(), unit, rewrite);
			newMethod.setReturnType2(newReturnType);
		}

		@SuppressWarnings("inferredcallout")
		protected void copyParameters(ASTRewrite rewrite, ICompilationUnit unit, MethodSpec oldMethod, IMethodNode newMethod, TypeVariableMaplet[] mapping) throws JavaModelException {
			SingleVariableDeclaration newDeclaration= null;
			for (int index= 0, size= oldMethod.parameters().size(); index < size; index++) {
				final SingleVariableDeclaration oldDeclaration= (SingleVariableDeclaration) oldMethod.parameters().get(index);
				if (mapping.length > 0)
					newDeclaration= createPlaceholderForSingleVariableDeclaration(oldDeclaration, unit, mapping, rewrite);
				else
					newDeclaration= createPlaceholderForSingleVariableDeclaration(oldDeclaration, unit, rewrite);
				newMethod.parameters().add(newDeclaration);
			}
		}

		@SuppressWarnings("inferredcallout")
		CalloutMappingDeclaration createNewCalloutDeclarationNode(CompilationUnitRewrite sourceRewrite, CompilationUnitRewrite targetRewrite, 
				IMethod sourceMethod, CalloutMappingDeclaration oldCallout, TypeVariableMaplet[] mapping, Map<IMember, IncomingMemberVisibilityAdjustment> adjustments, IProgressMonitor monitor, RefactoringStatus status) 
				throws JavaModelException 
		{
			final ASTRewrite rewrite= targetRewrite.getASTRewrite();
			final AST ast= rewrite.getAST();
			final CalloutMappingDeclaration newCallout= ast.newCalloutMappingDeclaration();
// TODO: copy parameter mappings:
//			if (!getDestinationType().isInterface())
//				copyBodyOfPulledUpMethod(sourceRewrite, targetRewrite, sourceMethod, oldCallout, newMethod, mapping, monitor);
			copyJavadocNode(rewrite, oldCallout, newCallout);
			int modifiers= getModifiersWithUpdatedVisibility(sourceMethod, sourceMethod.getFlags(), adjustments, monitor, true, status);

// TODO
//			copyAnnotations(oldCallout, newMethod);
			newCallout.modifiers().addAll(ASTNodeFactory.newModifiers(ast, modifiers));
			newCallout.setRoleMappingElement(createNewMethodSpec(ast, rewrite, mapping, (MethodSpec) oldCallout.getRoleMappingElement()));
			MethodMappingElement baseMappingElement = oldCallout.getBaseMappingElement();
			if (baseMappingElement instanceof MethodSpec) {
				newCallout.setBaseMappingElement(createNewMethodSpec(ast, rewrite, mapping, (MethodSpec) baseMappingElement));
			} else {
				newCallout.setBaseMappingElement(createNewFieldSpec(ast, rewrite, mapping, (FieldAccessSpec) baseMappingElement));
				newCallout.bindingOperator().setBindingModifier(ast.newModifier(oldCallout.bindingOperator().bindingModifier().getKeyword()));
			}
			newCallout.setSignatureFlag(oldCallout.hasSignature());
			return newCallout;
		}
		MethodSpec createNewMethodSpec(AST ast, ASTRewrite rewrite, TypeVariableMaplet[] mapping, MethodSpec oldMethodSpec) throws JavaModelException {
			MethodSpec newMethodSpec = ast.newMethodSpec();
			newMethodSpec.setName(((SimpleName) ASTNode.copySubtree(ast, oldMethodSpec.getName())));
			if (oldMethodSpec.hasSignature()) {
				copyReturnType(rewrite, getDeclaringType().getCompilationUnit(), oldMethodSpec, newMethodSpec, mapping);
				copyParameters(rewrite, getDeclaringType().getCompilationUnit(), oldMethodSpec, newMethodSpec, mapping);
				newMethodSpec.setSignatureFlag(oldMethodSpec.hasSignature());
//				copyTypeParameters(oldMethodSpec, newMethodSpec);
			}
			return newMethodSpec;
		}
		@SuppressWarnings("inferredcallout")
		FieldAccessSpec createNewFieldSpec(AST ast, ASTRewrite rewrite, TypeVariableMaplet[] mapping, FieldAccessSpec oldFieldSpec) throws JavaModelException {
			FieldAccessSpec newFieldSpec = ast.newFieldAccessSpec();
			newFieldSpec.setName(((SimpleName) ASTNode.copySubtree(ast, oldFieldSpec.getName())));
			if (oldFieldSpec.hasSignature()) {
				Type newFielType= null;
				if (mapping.length > 0)
					newFielType= createPlaceholderForType(oldFieldSpec.getFieldType(), getDeclaringType().getCompilationUnit(), mapping, rewrite);
				else
					newFielType= createPlaceholderForType(oldFieldSpec.getFieldType(), getDeclaringType().getCompilationUnit(), rewrite);
				newFieldSpec.setFieldType(newFielType);
				newFieldSpec.setSignatureFlag(oldFieldSpec.hasSignature());
			}
			return newFieldSpec;
		}
	}

	static CalloutMappingDeclaration getCalloutDeclarationNode(IMethod iMethod, CompilationUnit cuNode) throws JavaModelException {
		ASTNode node = NodeFinder.perform(cuNode, iMethod.getNameRange());
		return (CalloutMappingDeclaration)ASTNodes.getParent(node, CalloutMappingDeclaration.class);
	}

	/**
	 * Enable pull-up also for callout mappings. 
	 */
	protected class Availability playedBy RefactoringAvailabilityTester {

		boolean isPullUpAvailable(IMember member) <- replace boolean isPullUpAvailable(IMember member);

		static callin boolean isPullUpAvailable(IMember member) throws JavaModelException {
			if (base.isPullUpAvailable(member))
				return true;
			int kind = member.getElementType();
			switch (kind) {
			case IOTJavaElement.CALLOUT_MAPPING:
			case IOTJavaElement.CALLOUT_TO_FIELD_MAPPING:
				// extract from base method:
				if (!member.exists())
					return false;
				if (!Checks.isAvailable(member))
					return false;
				return true;
			default:
				return false;
			}
		}

		IMember[] getPullUpMembers(IType type) <- replace IMember[] getPullUpMembers(IType type);

		static callin IMember[] getPullUpMembers(IType type) throws JavaModelException {
			IMember[] result = base.getPullUpMembers(type);
			if (OTModelManager.isRole(type)) {
				List<IMember> callouts = new ArrayList<IMember>();
				for (IJavaElement elem : type.getChildren()) {
					switch (elem.getElementType()) {
					case IOTJavaElement.CALLOUT_MAPPING:
					case IOTJavaElement.CALLOUT_TO_FIELD_MAPPING:
						callouts.add((IMember) elem);
					}
				}
				if (callouts.size() > 0) {
					int l1 = result.length, l2 = callouts.size();
					IMember[] combined = new IMember[l1+l2];
					callouts.toArray(combined);
					System.arraycopy(result, 0, combined, l2, l1);
					return combined;
				}
			}
			return result;
		}		
	}

	/** Visibility checking for callout mappings. */
	protected team class Visibility playedBy MemberVisibilityAdjustor {

		IJavaElement getFReferencing() -> get IJavaElement fReferencing;

		void adjustOutgoingVisibility(IMember member, ModifierKeyword threshold, String template)
		-> void adjustOutgoingVisibility(IMember member, ModifierKeyword threshold, String template);

		ModifierKeyword thresholdTypeToMethod(IType referencing, IMethod referenced, IProgressMonitor monitor)
		-> ModifierKeyword thresholdTypeToMethod(IType referencing, IMethod referenced, IProgressMonitor monitor);
		
		checkOTMember <- replace adjustOutgoingVisibilityChain;

		@SuppressWarnings("basecall")
		callin void checkOTMember(IMember member, IProgressMonitor monitor) throws JavaModelException {
			try {
				base.checkOTMember(member, monitor);
			} catch (JavaModelException jme) {
				// when a MethodDeclarationMatch reports a SourceMethod representation actually a callout mapping
				// the method answers that it doesn't exist, that's what we intercept here:
				if (jme.getJavaModelStatus().isDoesNotExist()) {
					IType type = member.getDeclaringType();
					IOTType ottype = OTModelManager.getOTElement(type);
					if (ottype != null) {
						if (ottype.isRole() && member instanceof IMethod) {
							for (IMethodMapping map : ((IRoleType)ottype).getMethodMappings()) {
								if (map.getElementType() != IMethodMapping.CALLIN_MAPPING
										&& member.equals(map.getCorrespondingJavaElement())) 
								{
									if (!Modifier.isPublic(map.getFlags())) {
										final ModifierKeyword threshold= computeOutgoingVisibilityThreshold(map, monitor);
										adjustOutgoingVisibility(map, threshold, RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_method_warning);
									}
									if (member.getDeclaringType() != null)
										base.checkOTMember(member.getDeclaringType(), monitor);
									return;
								}
							}
						}
					}
				}
				throw jme;
			}
		}
		// adjusted copy, base version cannot handle OT elements
		private ModifierKeyword computeOutgoingVisibilityThreshold(final IMember referenced, final IProgressMonitor monitor) throws JavaModelException {
			final IJavaElement referencing = getFReferencing();
			Assert.isTrue(referencing instanceof ICompilationUnit || referencing instanceof IType || referencing instanceof IPackageFragment);
			ModifierKeyword keyword= ModifierKeyword.PUBLIC_KEYWORD;
			try {
				monitor.beginTask("", 1); //$NON-NLS-1$
				monitor.setTaskName(RefactoringCoreMessages.MemberVisibilityAdjustor_checking);
				final int referencingType= referencing.getElementType();
				final int referencedType= referenced.getElementType();
				switch (referencedType) {
					case IOTJavaElement.CALLOUT_TO_FIELD_MAPPING:
					case IOTJavaElement.CALLOUT_MAPPING: {
						final IMethodMapping calloutReferenced= (IMethodMapping) referenced;
						final ICompilationUnit referencedUnit= calloutReferenced.getCompilationUnit();
						switch (referencingType) {
							case IJavaElement.COMPILATION_UNIT: {
								final ICompilationUnit unit= (ICompilationUnit) referencing;
								if (referencedUnit != null && referencedUnit.equals(unit))
									keyword= ModifierKeyword.PRIVATE_KEYWORD;
								else if (referencedUnit != null && referencedUnit.getParent().equals(unit.getParent()))
									keyword= null;
								break;
							}
							case IJavaElement.TYPE: {
								keyword= thresholdTypeToMethod((IType) referencing, 
										(IMethod) calloutReferenced.getCorrespondingJavaElement(), monitor);
								break;
							}
							case IJavaElement.PACKAGE_FRAGMENT: {
								final IPackageFragment fragment= (IPackageFragment) referencing;
								if (calloutReferenced.getDeclaringType().getPackageFragment().equals(fragment))
									keyword= null;
								break;
							}
							default:
								Assert.isTrue(false);
						}
						break;
					}
					default:
						Assert.isTrue(false);
				}
			} finally {
				monitor.done();
			}
			return keyword;
		}
		
		// simple adjustment: for visibility checks in incoming direction the corresponding IMethod suffices:
		ModifierKeyword getVisibilityThreshold(IMember referenced)
		<- replace ModifierKeyword getVisibilityThreshold(IJavaElement referencing, IMember referenced, IProgressMonitor monitor)
			base when(referenced instanceof AbstractCalloutMapping)
			with { referenced <- referenced, result -> result }

		callin ModifierKeyword getVisibilityThreshold(IMember referencedMovedElement) throws JavaModelException {
			IMethod method = (IMethod) ((AbstractCalloutMapping)referencedMovedElement).getCorrespondingJavaElement();
			return base.getVisibilityThreshold(method);
		}

		adjustVisibility <- replace adjustVisibility;

		// --- during adjustMemberVisibility don't find decapsulating base method references:
		callin void adjustVisibility() throws JavaModelException {
			within (this) base.adjustVisibility();			
		}
		protected class Search playedBy BasicSearchEngine {
			searchDeclarations <- before searchDeclarations;
			private void searchDeclarations(IJavaElement element, SearchRequestor requestor, SearchPattern pattern, IProgressMonitor monitor) {
				if (pattern instanceof MethodPattern)
					((MethodPattern) pattern).findDecapsulationReferences = false;				
			}			
		}
		// ---
	}
	
	/**
	 * Method ReferenceFinderUtil.getMethodsReferencedIn
	 * should also report callout mappings as methods.
	 */
	protected class ReferenceFinder playedBy ReferenceFinderUtil {

		/** Adapt the method that filters METHOD elements. */
		Set<IJavaElement> extractMethods(SearchMatch[] searchResults)
		<- replace Set<IJavaElement> extractElements(SearchMatch[] searchResults, int elementType)
			base when (elementType == IJavaElement.METHOD);

		@SuppressWarnings("basecall")
		static callin Set<IJavaElement> extractMethods( SearchMatch[] searchResults) {
			Set<IJavaElement> elements= new HashSet<IJavaElement>();
			for (int i= 0; i < searchResults.length; i++) {
				IJavaElement el= SearchUtils.getEnclosingJavaElement(searchResults[i]);
				if (el instanceof IMember) {
					el = methodOrCallout((IMember) el);
					if (el != null)
						elements.add(el);
				}
			}
			return elements;
		}
		static IJavaElement methodOrCallout(IMember member) {
			int memberType = member.getElementType();
			if (member.exists()) {
				switch (memberType) {
				case IJavaElement.METHOD:
				case IOTJavaElement.CALLOUT_MAPPING:
				case IOTJavaElement.CALLOUT_TO_FIELD_MAPPING:
					return member;
				default: 
					return null;
				}
			}
            if (memberType == IJavaElement.METHOD) {
            	// search a callout mapping that might be "equal" to this method:
            	IType type = member.getDeclaringType();
            	try {
					for (IJavaElement child : type.getChildren()) {
						int elementType = child.getElementType();
						if (elementType == IOTJavaElement.CALLOUT_MAPPING || elementType == IOTJavaElement.CALLOUT_TO_FIELD_MAPPING) {
							AbstractCalloutMapping map = (AbstractCalloutMapping) child;
							if (member.equals(map.getCorrespondingJavaElement())) {
								return map;
							}
						}
					}
				} catch (JavaModelException e) {
					return null;
				}
            }
            return null;
		}
	}


	/** Help the first wizard page to avoid illegal settings (impossible pull-up of callout). */
	protected team class WizardPage playedBy PullUpMemberPage {

		/** Gateway to a private inner class: */
		protected class MemberActionInfo playedBy MemberActionInfo {

			int getNO_ACTION() 						-> get int NO_ACTION;
			
			protected IMember getMember()  			-> IMember getMember();			
			protected boolean hasAction() 			-> int getAction()
					with { result 					<- result != getNO_ACTION() }
			protected void setAction(int action) 	-> void setAction(int action);
		}

		int getDECLARE_ABSTRACT_ACTION()   -> get int DECLARE_ABSTRACT_ACTION;
		int getPULL_UP_ACTION() 		   -> get int PULL_UP_ACTION;

		MemberActionInfo[] getTableInput() -> MemberActionInfo[] getTableInput();
		IType getDestinationType()         -> IType getDestinationType();

		checkActionForCallouts <- before updateWizardPage;

		void checkActionForCallouts() {
			MemberActionInfo[] infos = getTableInput();
			for (MemberActionInfo info : infos) {
				if (!info.hasAction()) continue;
				IMember member = info.getMember();
				if (member instanceof AbstractCalloutMapping) {
					RefactoringStatus status = new RefactoringStatus();
					boolean haveError = false;
					try {
						PullUpRefactoringProcessorRole.checkDestinationForCallout((IMethod)member, getDestinationType(), status, new NullProgressMonitor());
						haveError = status.hasFatalError();
					} catch (JavaModelException e) {
						haveError = true;
					}
					if (haveError) {
						info.setAction(getDECLARE_ABSTRACT_ACTION());
					}
				}
			}
		}
	}

	protected class UseSuperTypeFix playedBy SuperTypeRefactoringProcessor {

		// === tell the base class how to cope with LiftingType references: ===
		
		void rewriteTypeOccurrence(TType arg0, CompilationUnitRewrite arg1, ASTNode arg2, TextEditGroup arg3)
		-> void rewriteTypeOccurrence(TType arg0, CompilationUnitRewrite arg1, ASTNode arg2, TextEditGroup arg3);
		
		void rewriteTypeOccurrence(final CompilationUnitRange range, final TType estimate, final ASTRequestor requestor, final CompilationUnitRewrite rewrite, final CompilationUnit copy, final Set<String> replacements, final TextEditGroup group)
		<- after
		void rewriteTypeOccurrence(final CompilationUnitRange range, final TType estimate, final ASTRequestor requestor, final CompilationUnitRewrite rewrite, final CompilationUnit copy, final Set<String> replacements, final TextEditGroup group);

		private void rewriteTypeOccurrence(CompilationUnitRange range, TType estimate, ASTRequestor requestor, CompilationUnitRewrite rewrite, CompilationUnit copy, Set<String> replacements, TextEditGroup group) 
		{
			ASTNode node= null;
			IBinding binding= null;
			final CompilationUnit target= rewrite.getRoot();
			node= NodeFinder.perform(copy, range.getSourceRange());
			if (node != null) {
				node= ASTNodes.getNormalizedNode(node);
				// OT: remember whether we saw the base side or the role side of a LiftingType:
				StructuralPropertyDescriptor locationInParent = node.getLocationInParent();
				node = node.getParent();
				if (node instanceof LiftingType) {
					// climb up one more step than base method does to find the argument (LT only occurs as an argument's type):
					VariableDeclaration argument = (VariableDeclaration) node.getParent();
					binding= argument.resolveBinding();
					node= target.findDeclaringNode(binding.getKey());
					if (node instanceof SingleVariableDeclaration) {
						// OT: drill into detail of LiftingType:
						ASTNode oldTypeNode = (ASTNode)((SingleVariableDeclaration)node).getType().getStructuralProperty(locationInParent);
						rewriteTypeOccurrence(estimate, rewrite, oldTypeNode, group);
						if (node.getParent() instanceof MethodDeclaration) {
							binding= ((VariableDeclaration) node).resolveBinding();
							if (binding != null)
								replacements.add(binding.getKey());
						}
					}
				}
			}
		}
	}
}
