FIr part 1 for  Bug 323327 -  [compiler] accessing a protected inner role from a private method of a nested team
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index 15304c6..5695680 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -1169,6 +1169,10 @@
 					case SyntheticMethodBinding.MethodAccess :
 					case SyntheticMethodBinding.SuperMethodAccess :
 					case SyntheticMethodBinding.BridgeMethod :
+//{ObjectTeams: more kinds:
+					case SyntheticMethodBinding.RoleMethodBridgeInner :
+					case SyntheticMethodBinding.RoleMethodBridgeOuter :
+// SH}
 						// generate a method info to emulate an access to a non-accessible method / super-method or bridge method
 						addSyntheticMethodAccessMethod(syntheticMethod);
 						break;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
index 8f4797a..c4e2d31 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
@@ -135,8 +135,8 @@
 
 //{ObjectTeams:
 	private boolean isDecapsulation = false;
-	// special case: the role method call in a callin wrapper needs special resolving
-	public boolean isCallinRoleMethodCall = false;
+	// special case: the role method call in a method pushed out to the enclosing team needs special resolving
+	public boolean isPushedOutRoleMethodCall = false;
 // SH}
 
 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
@@ -601,7 +601,7 @@
 		this.actualReceiverType = ((WeakenedTypeBinding)this.actualReceiverType).getStrongType();
 		this.bits |= NeedReceiverGenericCast; // addes a cast to this.actualReceiverType;
 	}
-	if (this.receiver.isThis() && !isQualifiedThis(this.receiver) && this.actualReceiverType.isRole()) {
+	if (this.receiver.isThis() && !receiverIsQualifiedThis() && this.actualReceiverType.isRole()) {
 		this.actualReceiverType = ((ReferenceBinding)this.actualReceiverType).getRealClass();
 		if (this.actualReceiverType == null) // happens with true role ifc
 			this.actualReceiverType = ((ReferenceBinding)this.receiver.resolvedType).getRealType();
@@ -624,7 +624,7 @@
 // SH}
 //{ObjectTeams: for calls to lower() resolve using internal selector _OT$getBase:
 	char[] realSelector = this.selector;
-	if (   CharOperation.equals(selector, IOTConstants.LOWER)
+	if (   CharOperation.equals(this.selector, IOTConstants.LOWER)
 		&& this.actualReceiverType.isRole()
 		&& this.arguments == null
 		&& this.actualReceiverType.isCompatibleWith(scope.getType(
@@ -864,7 +864,7 @@
 				} else {
 					// signature weakening might have produced the wrong returnType.
 					// check if we must cast this expression to the strengthened version:
-					returnType = checkStrengthenReturnType((ReferenceBinding)returnType, scope);
+					returnType = checkStrengthenReturnType(returnType, scope);
 				}
 			}
 // orig:
@@ -897,14 +897,14 @@
 }
 
 //{ObjectTeams: utils:
-private boolean isQualifiedThis(Expression receiver) {
-	if (receiver instanceof QualifiedThisReference)
+private boolean receiverIsQualifiedThis() {
+	if (this.receiver instanceof QualifiedThisReference)
 		return true;
-	if (receiver instanceof BaseReference)
-		return (((BaseReference)receiver).isQualified());
+	if (this.receiver instanceof BaseReference)
+		return (((BaseReference)this.receiver).isQualified());
 	return false;
 }
-protected boolean isDecapsulationAllowed(Scope scope) {
+public boolean isDecapsulationAllowed(Scope scope) {
 	// Note: methodScope() may return initializerScope, which has no Method, but the Type as refcontext.
 	if (scope.methodScope().referenceContext instanceof AbstractMethodDeclaration) {
 		AbstractMethodDeclaration method = (AbstractMethodDeclaration) scope.methodScope().referenceContext;
@@ -934,7 +934,7 @@
  */
 private Expression receiverForAnchorMapping(Scope scope) {
 	MethodScope methodScope = scope.methodScope();
-	if (methodScope != null && methodScope.isCallinWrapper() && this.isCallinRoleMethodCall)
+	if (methodScope != null && methodScope.isCallinWrapper() && this.isPushedOutRoleMethodCall)
     	return null; // pretend the call target is already "this" = the role.
 
 	return this.receiver;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
index 95f96b6..06aaf48 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
@@ -33,7 +33,7 @@
 import org.eclipse.objectteams.otdt.core.compiler.ISMAPConstants;
 import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
-import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticBaseCallSurrogate;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticOTMethodBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticRoleFieldAccess;
 
 /**
@@ -2581,8 +2581,8 @@
 public void generateSyntheticBodyForMethodAccess(SyntheticMethodBinding accessMethod) {
 	initializeMaxLocals(accessMethod);
 //{ObjectTeams: special treatment for this kind of access method:
-	if (accessMethod instanceof SyntheticBaseCallSurrogate) {
-		((SyntheticBaseCallSurrogate)accessMethod).generateInstructions(this);
+	if (accessMethod instanceof SyntheticOTMethodBinding) {
+		((SyntheticOTMethodBinding)accessMethod).generateInstructions(this);
 		return;
 	}
 //SH}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
index ca1b422..a88fbe7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
@@ -27,6 +27,7 @@
 import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
 import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.AnchorListAttribute;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticRoleBridgeMethodBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.TeamModel;
 import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.copyinheritance.CopyInheritance;
@@ -201,6 +202,8 @@
     		return false;
     	if (CharOperation.prefixEquals(IOTConstants.OT_SETFIELD, selector))
     		return false;
+    	if (SyntheticRoleBridgeMethodBinding.isPrivateBridgeSelector(selector))
+    		return false;
     	return declaringClass.isRole();
     }
     /** Implement {@link IProtectable#getDeclaringClass} */
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index 94b96fb..2dfdbb8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -2543,6 +2543,17 @@
 			if (methodBinding != null) return methodBinding;
 
 			methodBinding = findMethod(currentType, selector, argumentTypes, invocationSite);
+//{ObjectTeams: callout to private role method goes through the role class-part:
+			// (will later be replaced by synthetic accessor)
+			if (   methodBinding == null
+				&& invocationSite instanceof MessageSend
+				&& ((MessageSend)invocationSite).isDecapsulationAllowed(this) 
+				&& currentType.isRole())
+			{
+				currentType = currentType.getRealClass();
+				methodBinding = findMethod(currentType, selector, argumentTypes, invocationSite);
+			}
+// SH}
 			if (methodBinding == null)
 				return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound);
 			if (!methodBinding.isValidBinding())
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index 23d5e2c..b1b21a4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -46,6 +46,7 @@
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.*;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.AnchorMapping;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticBaseCallSurrogate;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticRoleBridgeMethodBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticRoleFieldAccess;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.*;
 import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.copyinheritance.CopyInheritance;
@@ -103,8 +104,14 @@
 	private final static int METHOD_EMUL = 0;
 	private final static int FIELD_EMUL = 1;
 	private final static int CLASS_LITERAL_EMUL = 2;
-
+//{ObjectTeams: these bridges are not to be found by addSyntheticMethod(MethodBinding,boolean), use only from callout:
+	private final static int ROLE_BRIDGE = 3;
+	
+	private final static int MAX_SYNTHETICS = 4;
+/* orig:
 	private final static int MAX_SYNTHETICS = 3;
+  :giro */
+// SH}
 
 	HashMap[] synthetics;
 	char[] genericReferenceTypeSignature;
@@ -718,7 +725,8 @@
 	}
 	return accessMethod;
 }
-//{ObjectTeams: add synthetic (mostly empty) basecall surrogate
+//{ObjectTeams: add OT-specific synthetic bridges:
+// (mostly empty) basecall surrogate
 public SyntheticMethodBinding addSyntheticBaseCallSurrogate(MethodBinding callinMethod) {
 	if (this.synthetics == null)
 		this.synthetics = new HashMap[MAX_SYNTHETICS];
@@ -739,6 +747,34 @@
 	}
 	return accessMethod;	
 }
+// bridges towards a private role method
+public SyntheticMethodBinding addSyntheticRoleMethodBridge(SourceTypeBinding declaringRole, MethodBinding targetMethod, int bridgeKind) {
+	if (this.synthetics == null)
+		this.synthetics = new HashMap[MAX_SYNTHETICS];
+	if (this.synthetics[SourceTypeBinding.ROLE_BRIDGE] == null)
+		this.synthetics[SourceTypeBinding.ROLE_BRIDGE] = new HashMap(5);
+
+	SyntheticMethodBinding accessMethod = (SyntheticMethodBinding) this.synthetics[SourceTypeBinding.ROLE_BRIDGE].get(targetMethod);
+	if (accessMethod == null) {
+		accessMethod = new SyntheticRoleBridgeMethodBinding(declaringRole, targetMethod, bridgeKind);
+		this.synthetics[SourceTypeBinding.ROLE_BRIDGE].put(targetMethod, accessMethod);
+	}
+	return accessMethod;	
+}
+// and retrieve an existing accessor:
+public SyntheticMethodBinding findOuterRoleMethodSyntheticAccessor(MethodBinding targetMethod) {
+	SyntheticMethodBinding accessor; 
+	if (this.synthetics != null) {
+		accessor = (SyntheticMethodBinding) this.synthetics[ROLE_BRIDGE].get(targetMethod);
+		if (accessor != null) {
+			if (accessor.isStatic())
+				return ((SourceTypeBinding)enclosingType()).findOuterRoleMethodSyntheticAccessor(accessor);
+			else 
+				return accessor;
+		}
+	}
+	return null;
+}
 // SH}
 /*
  * Record the fact that bridge methods need to be generated to override certain inherited methods
@@ -2064,6 +2100,16 @@
 		return method; // but its still unresolved with a null return type & is still connected to its method declaration
 
 	method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
+//{ObjectTeams: need role method bridges?
+	if (   isRole() 
+		&& ((method.modifiers & ClassFileConstants.AccPrivate) != 0) 
+		&& !CharOperation.prefixEquals(IOTConstants.OT_DOLLAR_NAME, method.selector)
+		&& !methodDecl.isConstructor()) 
+	{
+		MethodBinding inner = addSyntheticRoleMethodBridge(this, method, SyntheticMethodBinding.RoleMethodBridgeInner);
+		((SourceTypeBinding) enclosingType()).addSyntheticRoleMethodBridge(this, inner, SyntheticMethodBinding.RoleMethodBridgeOuter);
+	}
+// SH}
 	return method;
 }
 //{ObjectTeams: helper to find args allowing baseclass decapsulation:
@@ -2317,6 +2363,8 @@
 }
 
 public SyntheticMethodBinding[] syntheticMethods() {
+//{ObjectTeams: two different kinds of synthetics:
+/* orig:
 	if (this.synthetics == null 
 			|| this.synthetics[SourceTypeBinding.METHOD_EMUL] == null 
 			|| this.synthetics[SourceTypeBinding.METHOD_EMUL].size() == 0) {
@@ -2325,6 +2373,13 @@
 	// difficult to compute size up front because of the embedded arrays so assume there is only 1
 	int index = 0;
 	SyntheticMethodBinding[] bindings = new SyntheticMethodBinding[1];
+ :giro */
+  if (this.synthetics == null) return null;
+  int index = 0;
+  SyntheticMethodBinding[] bindings = new SyntheticMethodBinding[1];
+  if (this.synthetics[SourceTypeBinding.METHOD_EMUL] != null && this.synthetics[METHOD_EMUL].size() > 0) 
+  {
+//orig:
 	Iterator methodArrayIterator = this.synthetics[SourceTypeBinding.METHOD_EMUL].values().iterator();
 	while (methodArrayIterator.hasNext()) {
 		SyntheticMethodBinding[] methodAccessors = (SyntheticMethodBinding[]) methodArrayIterator.next();
@@ -2337,6 +2392,25 @@
 			}
 		}
 	}
+  }
+// :giro
+// more synthetics to generate:
+  	if (this.synthetics[SourceTypeBinding.ROLE_BRIDGE] != null && this.synthetics[SourceTypeBinding.ROLE_BRIDGE].size() > 0) 
+  	{
+		Iterator methodArrayIterator = this.synthetics[SourceTypeBinding.ROLE_BRIDGE].values().iterator();
+		while (methodArrayIterator.hasNext()) {
+			SyntheticMethodBinding methodAccessor = (SyntheticMethodBinding) methodArrayIterator.next();
+			if (methodAccessor != null) {
+				if (index+1 > bindings.length) {
+					System.arraycopy(bindings, 0, (bindings = new SyntheticMethodBinding[index + 1]), 0, index);
+				}
+				bindings[index++] = methodAccessor; 
+			}
+		}
+	}
+  	if (index == 0)
+  		return null; // nothing found
+// SH}
 	// sort them in according to their own indexes
 	int length;
 	SyntheticMethodBinding[] sortedBindings = new SyntheticMethodBinding[length = bindings.length];
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
index e20c982..52e1ecf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
@@ -49,8 +49,10 @@
 	public final static int EnumValues = 9; // enum #values()
 	public final static int EnumValueOf = 10; // enum #valueOf(String)
 	public final static int SwitchTable = 11; // switch table method
-//{ObjectTeams: another purpose:
+//{ObjectTeams: other purposes:
 	public final static int InferredCalloutToField = 12; // calling an inferred callout-to-field
+	public final static int RoleMethodBridgeOuter = 13; // a team-level bridge method towards a private role method (for callout)
+	public final static int RoleMethodBridgeInner = 14; // a role-level bridge method towards a private role method (for callout)
 // SH}
 
 	public int sourceStart = 0; // start position of the matching declaration
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseAllocationExpression.java
index edc12fc..bfd9cbf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseAllocationExpression.java
@@ -159,7 +159,7 @@
 
         	MessageSend allocSend = new MessageSend() {
         		@Override
-        		protected boolean isDecapsulationAllowed(Scope scope2) {
+				public boolean isDecapsulationAllowed(Scope scope2) {
         			// this message send can decapsulate independent of scope
         			return true;
         		}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/SyntheticBaseCallSurrogate.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/SyntheticBaseCallSurrogate.java
index 9fe2bba..7f9b664 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/SyntheticBaseCallSurrogate.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/SyntheticBaseCallSurrogate.java
@@ -47,7 +47,7 @@
  * @author stephan
  * @since 1.3.0
  */
-public class SyntheticBaseCallSurrogate extends SyntheticMethodBinding
+public class SyntheticBaseCallSurrogate extends SyntheticOTMethodBinding
 {
 	// this corresponds to IOTConstants.OT_DOLLAR_NAME without the trailing '$':
 	private static final char[] _OT = "_OT".toCharArray(); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/SyntheticOTMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/SyntheticOTMethodBinding.java
new file mode 100644
index 0000000..4c26576
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/SyntheticOTMethodBinding.java
@@ -0,0 +1,33 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ * 
+ * Copyright 2010 GK Software AG
+ * 
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id$
+ * 
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ * 
+ * Contributors:
+ * 	  Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.internal.core.compiler.lookup;
+
+import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+public abstract class SyntheticOTMethodBinding extends SyntheticMethodBinding {
+
+	public SyntheticOTMethodBinding(SourceTypeBinding declaringClass, int modifiers, char[] selector, TypeBinding[] parameters, TypeBinding returnType) 
+	{
+		super(declaringClass, modifiers, selector, parameters, returnType);
+	}
+
+	public abstract	void generateInstructions(CodeStream codeStream);
+
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/SyntheticRoleBridgeMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/SyntheticRoleBridgeMethodBinding.java
new file mode 100644
index 0000000..23a6fed
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/SyntheticRoleBridgeMethodBinding.java
@@ -0,0 +1,171 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ * 
+ * Copyright 2010 GK Software AG
+ * 
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * $Id$
+ * 
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ * 
+ * Contributors:
+ * 	  Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.internal.core.compiler.lookup;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
+import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstConverter;
+import org.eclipse.objectteams.otdt.internal.core.compiler.util.TypeAnalyzer;
+
+public class SyntheticRoleBridgeMethodBinding extends SyntheticOTMethodBinding {
+
+	public SyntheticRoleBridgeMethodBinding(SourceTypeBinding declaringRole, MethodBinding targetMethod, int bridgeKind) {
+		super(declaringRole, ClassFileConstants.AccPublic|ClassFileConstants.AccSynthetic, targetMethod.selector, targetMethod.parameters, targetMethod.returnType);
+		this.purpose = bridgeKind;
+		switch (bridgeKind) {
+			case RoleMethodBridgeOuter:
+				// correction: this method sits in the team not the role:
+				this.declaringClass = declaringRole.enclosingType();
+				break;
+			case RoleMethodBridgeInner:
+				// correction: add role as first parameter:
+				int len = targetMethod.parameters.length;
+				int offset = targetMethod.isStatic()?2:0;
+				this.parameters = new TypeBinding[len+1+offset];
+				this.parameters[0] = declaringRole.getRealType();
+				if (offset > 0) {
+					this.parameters[1] = TypeBinding.INT;				// dummy int
+					this.parameters[2] = declaringRole.enclosingType(); // team arg
+				}
+				System.arraycopy(targetMethod.parameters, 0, this.parameters, 1+offset, len);
+				// correction: this bridge is static:
+				this.modifiers |= ClassFileConstants.AccStatic;
+				// correction: generate the bridge method name:
+				this.selector = SyntheticRoleBridgeMethodBinding.getPrivateBridgeSelector(targetMethod.selector, declaringRole.sourceName());
+				break;
+		}
+		this.targetMethod = targetMethod;
+		this.thrownExceptions = targetMethod.thrownExceptions;
+		this.typeVariables = targetMethod.typeVariables;
+		SyntheticMethodBinding[] knownAccessMethods = ((SourceTypeBinding) this.declaringClass).syntheticMethods();
+		int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
+		this.index = methodId;
+	}
+
+	@Override
+	public void generateInstructions(CodeStream codeStream) {
+		TypeBinding[] arguments = this.parameters;
+		int argLen = arguments.length;
+		TypeBinding[] targetParameters = this.targetMethod.parameters;
+		int resolvedPosition = 0;
+		int argIdx = 0;
+		int targetIdx = 0;
+		switch (this.purpose) {
+			case RoleMethodBridgeInner:
+				codeStream.aload_0(); // synthetic first arg is the receiver role
+				codeStream.checkcast(this.targetMethod.declaringClass);
+				resolvedPosition = 1; // first arg is processed
+				argIdx = 1;
+				if (this.targetMethod.isStatic()) {
+					codeStream.iconst_0(); // dummy int
+					codeStream.aload_2(); // pass synth. team arg
+					argIdx += 2;
+					resolvedPosition += 2;
+				}
+				break;
+			case RoleMethodBridgeOuter:
+				resolvedPosition = 1; // ignore team instance at 0
+				argIdx = 0; 		  // pass all args unchanged
+				break;
+		}
+		while (argIdx < argLen) {
+		    TypeBinding parameter = targetParameters[targetIdx++];
+		    TypeBinding argument = arguments[argIdx++];
+			codeStream.load(argument, resolvedPosition);
+			if (argument != parameter)
+				codeStream.checkcast(parameter);
+			switch(parameter.id) {
+				case TypeIds.T_long :
+				case TypeIds.T_double :
+					resolvedPosition += 2;
+					break;
+				default :
+					resolvedPosition++;
+					break;
+			}
+		}
+		switch (this.purpose) {
+			case RoleMethodBridgeInner :
+				// call the private role method
+				codeStream.invoke(Opcodes.OPC_invokespecial, this.targetMethod, null);
+				break;
+			case RoleMethodBridgeOuter :
+				// call the static role method bridge:
+				codeStream.invoke(Opcodes.OPC_invokestatic, this.targetMethod, null);
+				break;
+		}
+		switch (this.targetMethod.returnType.id) {
+			case TypeIds.T_void :
+				codeStream.return_();
+				break;
+			case TypeIds.T_boolean :
+			case TypeIds.T_byte :
+			case TypeIds.T_char :
+			case TypeIds.T_short :
+			case TypeIds.T_int :
+				codeStream.ireturn();
+				break;
+			case TypeIds.T_long :
+				codeStream.lreturn();
+				break;
+			case TypeIds.T_float :
+				codeStream.freturn();
+				break;
+			case TypeIds.T_double :
+				codeStream.dreturn();
+				break;
+			default :
+				codeStream.areturn();
+		}
+	}
+
+	public static char[] getPrivateBridgeSelector(char[] selector, char[] roleName) {
+		return CharOperation.concat(
+				CharOperation.concat(IOTConstants.OT_DOLLAR_NAME, roleName),
+				CharOperation.concat(AstConverter.PRIVATE, selector));
+	}
+
+	public static boolean isPrivateBridgeSelector(char[] selector) {
+		if (!CharOperation.prefixEquals(IOTConstants.OT_DOLLAR_NAME, selector))
+			return false;
+		return CharOperation.indexOf(AstConverter.PRIVATE, selector, true, IOTConstants.OT_DOLLAR_LEN) > -1;
+	}
+
+	public static MethodBinding findOuterAccessor(Scope scope, ReferenceBinding roleType, MethodBinding targetMethod) {
+		ReferenceBinding roleClass = roleType.getRealClass();
+		if (roleClass instanceof SourceTypeBinding)
+			return ((SourceTypeBinding)roleClass).findOuterRoleMethodSyntheticAccessor(targetMethod);
+		// for binary type find it in the team's regular methods:
+		int len = targetMethod.parameters.length;
+		TypeBinding[] extendedParamters = new TypeBinding[len+1];
+		extendedParamters[0] = roleType;
+		System.arraycopy(targetMethod.parameters, 0, extendedParamters, 1, len);
+		char[] selector = getPrivateBridgeSelector(targetMethod.selector, roleType.sourceName());
+		return TypeAnalyzer.findMethod(scope, roleType.enclosingType(), selector, extendedParamters);
+	}
+
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementor.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementor.java
index 2f533d7..73822b0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementor.java
@@ -585,7 +585,7 @@
 
 		// ------------- the role message send:
 		MessageSend roleMessageSend = gen.messageSend(receiver, roleMethodName, messageSendArguments);
-		roleMessageSend.isCallinRoleMethodCall = true;
+		roleMessageSend.isPushedOutRoleMethodCall = true;
 
 		// ---------------- store or ignore the result:
 		if (   callinBindingDeclaration.isReplaceCallin())
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java
index 36ca4b5..6ac87a4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java
@@ -420,7 +420,7 @@
 					}
 					// -- assemble the method call:
 					MessageSend roleMethodCall = gen.messageSend(receiver, callinDecl.roleMethodSpec.selector, callArgs);
-					roleMethodCall.isCallinRoleMethodCall = true;
+					roleMethodCall.isPushedOutRoleMethodCall = true;
 					if (isReplace) {
 						blockStatements[statIdx] = gen.returnStatement(roleMethodCall);
 					} else {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementor.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementor.java
index e174c7d..3b4f72f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementor.java
@@ -77,6 +77,7 @@
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.DependentTypeBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.ITeamAnchor;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticRoleBridgeMethodBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.TThisBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.WeakenedTypeBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.FieldModel;
@@ -85,7 +86,6 @@
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.TeamModel;
 import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.AbstractStatementsGenerator;
 import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstClone;
-import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstConverter;
 import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstEdit;
 import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstGenerator;
 import org.eclipse.objectteams.otdt.internal.core.compiler.util.IProtectable;
@@ -547,7 +547,7 @@
         // because the method body is a call to the method specific by the spec.
         sStart = calloutDecl.baseMethodSpec.sourceStart;
         sEnd   = calloutDecl.baseMethodSpec.sourceEnd;
-        AstGenerator gen = new AstGenerator(sStart, sEnd);
+        final AstGenerator gen = new AstGenerator(sStart, sEnd);
 
         Expression receiver;
         char[] selector = calloutDecl.baseMethodSpec.selector;
@@ -560,6 +560,7 @@
 							gen.baseclassReference(baseType),
 							CastExpression.DO_WRAP);
 
+		MessageSend messageSend;
     	if (calloutDecl.baseMethodSpec.isPrivate() && baseType.isRole()) {
     		// tricky case: callout to a private role method (base-side)
     		// requires the indirection via two wrapper methods (privateBridgeMethod)
@@ -571,30 +572,43 @@
     		// generated message send refers to public bridge, report decapsulation now:
     		calloutDecl.scope.problemReporter().decapsulation(calloutDecl.baseMethodSpec, baseType, calloutDecl.scope);
 
-    		// determine the receiver: convert the team anchor into an expression
-    		receiver = gen.typeAnchorReference(((RoleTypeBinding)baseType)._teamAnchor);
-    		((TypeAnchorReference)receiver).isExpression = true;
+//    		if (!(calloutDecl.baseMethodSpec instanceof FieldAccessSpec)) {
+//	    		// one more argument: the base instance:
+//	    		int len = arguments.length;
+//	    		System.arraycopy(arguments, 0,
+//	    				         arguments = new Expression[len+1], 1,
+//	    				         len);
+//    		}
+//    		// add to front (callout-to-method), or simply replace (callout-to-field) first arg:
+//	    	arguments[0] = gen.baseNameReference(IOTConstants._OT_BASE);
 
-    		// now get the bridge method (at the base-side team)
-    		selector = AstConverter.getPrivateBridgeSelector(selector, baseType.sourceName());
+	    	messageSend = new MessageSend() {
+	    		@Override
+	    		public void generateCode(org.eclipse.jdt.internal.compiler.lookup.BlockScope currentScope, org.eclipse.jdt.internal.compiler.codegen.CodeStream codeStream, boolean valueRequired) {
+	    			// manually redirect to synth bridge:
+	    			// new receiver is the anchor denoting the base role's enclosing team instance:
+	    			TypeAnchorReference syntheticReceiver = gen.typeAnchorReference(((RoleTypeBinding)this.actualReceiverType)._teamAnchor);
+	    			syntheticReceiver.isExpression = true;
+	    			syntheticReceiver.resolve(currentScope);
+	    			syntheticReceiver.generateCode(currentScope, codeStream, true/*valueRequired*/);
+	    			// directly use the accessor and its declaring class for the invoke instruction:
+	    			this.binding = this.syntheticAccessor;
+	    			this.actualReceiverType = this.syntheticAccessor.declaringClass;
+	    			this.syntheticAccessor = null;
+	    			super.generateCode(currentScope, codeStream, valueRequired);
+	    		}
+	    	};
+	    	MethodBinding targetMethod = calloutDecl.baseMethodSpec.resolvedMethod;
+	    	messageSend.syntheticAccessor = SyntheticRoleBridgeMethodBinding.findOuterAccessor(calloutDecl.scope, baseType, targetMethod);
+	    	messageSend.receiver = receiver;
+	    	messageSend.selector = selector;
+	    	messageSend.arguments = arguments;
+	    	messageSend.sourceStart = sStart;
+	    	messageSend.sourceEnd = sEnd;
+    	} else {
 
-    		if (!(calloutDecl.baseMethodSpec instanceof FieldAccessSpec)) {
-	    		// one more argument: the base instance:
-	    		int len = arguments.length;
-	    		System.arraycopy(arguments, 0,
-	    				         arguments = new Expression[len+1], 1,
-	    				         len);
-    		}
-    		// add to front (callout-to-method), or simply replace (callout-to-field) first arg:
-	    	arguments[0] = gen.baseNameReference(IOTConstants._OT_BASE);
+    		messageSend = gen.messageSend(receiver, selector, arguments);
     	}
-
-		MessageSend messageSend = gen.messageSend
-		    (
-        		receiver,
-        		selector,
-				arguments
-			);
         // TODO(SH): create receiver via gen, too.
         messageSend.receiver.sourceStart = sStart;
         messageSend.receiver.sourceEnd   = sEnd;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java
index 57bd8e9..d109903 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java
@@ -91,6 +91,7 @@
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.DependentTypeBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticBaseCallSurrogate;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticRoleBridgeMethodBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticRoleFieldAccess;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.WeakenedTypeBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel;
@@ -877,6 +878,8 @@
 			// some, but not all, synthetics shall be generated with strong signatures as indicated by 'site':
 			if (!SyntheticBaseCallSurrogate.isBaseCallSurrogateName(method.selector))
 				site = targetRoleDecl.binding;
+			if (SyntheticRoleBridgeMethodBinding.isPrivateBridgeSelector(method.selector))
+				return; // will be generated anew
 		}
 
 		if (TypeContainerMethod.isTypeContainer(method))
@@ -1035,25 +1038,6 @@
 	    	newMethodDecl.isMappingWrapper = WrapperKind.CALLIN;
 
 	    if (methodFound == null) {
-	    	if (   method.isPrivate() // private role methods need special preparation for callout:
-	    		&& !CharOperation.prefixEquals(IOTConstants.OT_DOLLAR_NAME, method.selector)
-	    		&& !method.isConstructor()
-	    		&& !targetRoleDecl.isInterface())
-	    	{
-	    		// re-create (override) bridge methods which are _not_ copied (fake methods):
-	    		AstEdit.addMethod(targetTeamDecl,
-	    				AstConverter.genBridgeForPrivateRoleMethod(targetTeamDecl,
-	    												     targetRoleDecl,
-	    													 srcRole.sourceName(),
-	    													 (MethodDeclaration)newMethodDecl,
-	    													 /*teamPart*/true));
-	    		AstEdit.addMethod(targetRoleDecl,
-	    				AstConverter.genBridgeForPrivateRoleMethod(targetTeamDecl,
-	    												     targetRoleDecl,
-	    													 srcRole.sourceName(),
-	    													 (MethodDeclaration)newMethodDecl,
-	    													 /*teamPart*/false));
-	    	}
 	    	// copy down some more properties:
 	    	if (TSuperHelper.isTSuper(method))
 	    		newMethodDecl.isTSuper = true;
@@ -1149,20 +1133,6 @@
 				srcMethod.resolveTypes();
 				srcMethod.resolvedField();
 				copySyntheticMethod(srcMethod, tgtTeamDecl, tgtTeamDecl);
-			} else if (AstConverter.isPrivateBridgeSelector(method.selector)) {
-				TypeBinding roleType = TeamModel.strengthenRoleType(tgtTeamDecl.binding, method.parameters[0]);
-				// need to create team part of a bridge to a binary (re-used) role?
-				if (roleType instanceof ReferenceBinding && ((ReferenceBinding)roleType).isBinaryBinding()) { 
-					// _OT$Role$private$selector <- pick selector (may contain more $s)
-					int start = CharOperation.indexOf('$', method.selector, IOTConstants.OT_DOLLAR_LEN)+AstConverter.PRIVATE.length;
-					char[] targetSelector = CharOperation.subarray(method.selector, start, -1); 
-					if (CharOperation.prefixEquals(IOTConstants.OT_GETFIELD, targetSelector))
-						; // FIXME(SH): implement copying bridge to fieldget
-					else if (CharOperation.prefixEquals(IOTConstants.OT_SETFIELD, targetSelector))
-						; // FIXME(SH): implement copying bridge to fieldset
-					else
-						copyPrivateRoleMethodBridge(tgtTeamDecl, roleType, method, targetSelector);
-				}
 			}
 		}
 	}
@@ -1177,33 +1147,6 @@
 		if (dstMethod != null)
 			tgtRoleModel.addSyntheticMethodMapping(srcMethod, dstMethod);
     }
-    
-    private static void copyPrivateRoleMethodBridge(TypeDeclaration tgtTeamDecl, TypeBinding roleType, MethodBinding superMethod, char[] targetSelector) 
-    {
-		ReferenceBinding tgtTeam = tgtTeamDecl.binding;
-		AstGenerator gen = new AstGenerator(tgtTeamDecl);
-		gen.replaceableEnclosingClass = tgtTeam; // like during copyMethod
-		
-		MethodDeclaration newMethodDecl = (MethodDeclaration)AstConverter.createMethod(superMethod, 
-																					   tgtTeam, 
-																					   tgtTeamDecl.compilationResult, 
-																					   DecapsulationState.REPORTED, 
-																					   gen);
-		// we will *not* copy byte code:
-		newMethodDecl.isCopied = false;
-		
-		// but generate AST:
-		newMethodDecl.arguments[0].name = AstConverter.ROLE_ARG_NAME;
-		AstConverter.genPrivateRoleMethodBridgeStatements(targetSelector,
-														  false,  						   // isStatic is irrelevant for team part
-														  superMethod.parameters.length-1, // source args len not including role arg 
-														  newMethodDecl, 
-														  roleType.sourceName(), 
-														  true, 						   // teamPart
-														  gen);
-		
-		AstEdit.addMethod(tgtTeamDecl, newMethodDecl, false/*wasSynthetic*/, false/*addToFront*/);
-    }
 
 	/**
      * Copy a synthetic access method to `tgtTypeDecl'.
@@ -1267,6 +1210,9 @@
     			if (dstMethod == null)
     				tgtTypeDecl.scope.problemReporter().abortDueToInternalError("Expected synthetic bridge method does not exist: "+new String(srcMethod.readableName())); //$NON-NLS-1$
     			break;
+    		case SyntheticMethodBinding.RoleMethodBridgeInner:
+    		case SyntheticMethodBinding.RoleMethodBridgeOuter:
+    			return null; // not copied but generated anew
     		default:
     			tgtTypeDecl.scope.problemReporter().abortDueToInternalError("Synthetic methods only partially supported"); //$NON-NLS-1$
     		}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/RoleSplitter.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/RoleSplitter.java
index 96e3b8a..d9bcad1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/RoleSplitter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/RoleSplitter.java
@@ -204,24 +204,6 @@
 									newmethod.binding.tagBits |= TagBits.AnnotationDeprecated;
 								}
 							}});
-					} else {
-						// private methods add a wrapper chain to team/role:
-						final MethodDeclaration bridge1 = AstConverter.genBridgeForPrivateRoleMethod(
-																teamDecl, roleClassDecl, roleIfcDecl.name, method, true);
-						AstEdit.addMethodDeclOnly(teamDecl, bridge1, false);
-						if (teamDecl.binding != null && bridge1.binding == null)
-							roleIfcDecl.getRoleModel()._state.addJob(ITranslationStates.STATE_ROLES_LINKED,
-								new Runnable() { public void run() {
-									teamDecl.binding.resolveGeneratedMethod(bridge1, false);
-								}});
-						final MethodDeclaration bridge2 = AstConverter.genBridgeForPrivateRoleMethod(
-														        teamDecl, roleClassDecl, roleIfcDecl.name, method, false);
-						AstEdit.addMethodDeclOnly(roleClassDecl, bridge2, false);
-						if (teamDecl.binding != null && bridge2.binding == null)
-							roleClassDecl.getRoleModel()._state.addJob(ITranslationStates.STATE_ROLES_LINKED,
-								new Runnable() { public void run() {
-									roleClassDecl.binding.resolveGeneratedMethod(bridge2, false);
-								}});
 					}
                 }
 			}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstConverter.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstConverter.java
index 242d939..b496b00 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstConverter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstConverter.java
@@ -69,10 +69,10 @@
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
 import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
-import org.eclipse.objectteams.otdt.internal.core.compiler.ast.LiftingTypeReference;
 import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.ConstantPoolObjectMapper;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.AnchorMapping;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticRoleBridgeMethodBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel.FakeKind;
 
@@ -489,129 +489,6 @@
 		return newmethod;
 	}
 
-	public static char[] getPrivateBridgeSelector(char[] selector, char[] roleName) {
-		return CharOperation.concat(
-				CharOperation.concat(OT_DOLLAR_NAME, roleName),
-				CharOperation.concat(PRIVATE, selector));
-	}
-
-	public static boolean isPrivateBridgeSelector(char[] selector) {
-		if (!CharOperation.prefixEquals(OT_DOLLAR_NAME, selector))
-			return false;
-		return CharOperation.indexOf(PRIVATE, selector, true, OT_DOLLAR_LEN) > -1;
-	}
-
-	/**
-	 * Generate a method that bridges from a callout to a private role method.
-	 * @param teamDecl
-	 * @param roleName
-	 * @param privateRoleMethod
-	 * @param teamPart select whether the team part should be created or the role part.
-	 * @return the new method.
-	 */
-	public static MethodDeclaration genBridgeForPrivateRoleMethod(TypeDeclaration   teamDecl,
-																  TypeDeclaration   roleDecl,
-															      char[]            roleName,
-															      MethodDeclaration privateRoleMethod,
-															      boolean           teamPart)
-	{
-		// teamMeth looks like this (delegates to role method below):
-		// public T MyTeam._OT$R$private$m(R _OT$role, args) {
-		//     [return] __OT__R._OT$R$private$m(_OT$role, args);
-		// }
-
-		// roleMeth looks like this (delegates to original private method):
-		// public static T _OT$R$private$m(R _OT$role, args) {
-		//    [return] ((__OT__R)_OT$role).m(args);
-		// }
-
-		AstGenerator gen = (teamPart && roleDecl.isRoleFile())  
-			? new AstGenerator(teamDecl.sourceStart, teamDecl.sourceEnd) // have no better position
-			: new AstGenerator(privateRoleMethod.sourceStart, privateRoleMethod.sourceEnd);
-
-		MethodDeclaration meth = AstClone.copyMethod(teamPart?teamDecl:roleDecl, privateRoleMethod, gen);
-
-		meth.modifiers = AccPublic;
-		if (!teamPart)
-			meth.modifiers |= AccStatic;
-
-		meth.selector = getPrivateBridgeSelector(meth.selector, roleName);
-
-		// add role argument to front of arguments:
-		int len = 0;
-		if (meth.arguments != null) {
-			len = meth.arguments.length;
-			System.arraycopy(meth.arguments, 0,
-					meth.arguments = new Argument[len+1], 1,
-					len);
-			for (int i=1; i < len+1; i++)
-				if (meth.arguments[i].type instanceof LiftingTypeReference) // defer the declared lifting to the original method
-					meth.arguments[i].type = AstClone.copyTypeReference(((LiftingTypeReference)meth.arguments[i].type).baseReference);
-		} else {
-			meth.arguments = new Argument[1];
-		}
-		meth.arguments[0] = gen.argument(ROLE_ARG_NAME, gen.singleTypeReference(roleName), AccFinal);
-
-		if (!roleDecl.isConverted) {
-			genPrivateRoleMethodBridgeStatements(privateRoleMethod.selector, privateRoleMethod.isStatic(), len, meth, roleName, teamPart, gen); 
-			meth.hasParsedStatements = true;
-		}
-		MethodModel model = MethodModel.getModel(meth);
-		model._fakeKind= FakeKind.ROLE_FEATURE_BRIDGE;
-		model._thisSubstitution = meth.arguments[0];
-		if (teamPart)
-			model._sourceDeclaringType = roleDecl;
-		return meth;
-	}
-
-	public static void genPrivateRoleMethodBridgeStatements (char[]				selector,
-															 boolean 		 	isStatic, // irrelevant for team part
-															 int 				srcArgsLen, 
-															 MethodDeclaration 	bridgeMethod,
-															 char[] 		   	roleName,
-															 boolean 		   	isTeamPart, 
-															 AstGenerator 		gen) 
-	{
-		char[] roleClassName = CharOperation.concat(OT_DELIM_NAME, roleName);
-
-		int offset = 0; // into call arguments (0 or 1)
-		Expression   receiver;
-		if (isTeamPart) {
-			receiver = gen.singleNameReference(roleClassName); // __OT__R.
-			selector = bridgeMethod.selector;						   // _OT$R$private$m
-			offset = 1; // call arguments include role arg
-		} else {
-			if (isStatic)
-				receiver = gen.singleNameReference(roleClassName); // __OT__R.
-			else
-				receiver = gen.castExpression(					   // ((__OT__R)_OT$role).
-						gen.singleNameReference(ROLE_ARG_NAME),
-						gen.singleTypeReference(roleClassName),
-						CastExpression.RAW);
-			// plain call arguments (no offset)
-		}
-
-		// call params differ (according to offset)
-		Expression[] params = new Expression[srcArgsLen+offset];
-		for (int i=0; i<srcArgsLen; i++)
-			params[i+offset] = gen.singleNameReference(bridgeMethod.arguments[i+1].name);
-		if (offset == 1)
-			params[0] = gen.singleNameReference(ROLE_ARG_NAME);
-
-		// assemble call:
-		Expression call = gen.messageSend(receiver, selector, params);
-
-
-		if (   bridgeMethod.returnType instanceof SingleTypeReference
-			&& CharOperation.equals(((SingleTypeReference)bridgeMethod.returnType).token,
-					                 TypeConstants.VOID))
-		{
-			bridgeMethod.statements = new Statement[]{ call };
-		} else {
-			bridgeMethod.statements = new Statement[]{ gen.returnStatement(call) };
-		}
-	}
-
 	/**
 	 * Generate a method that bridges from a callout to a private role field.
 	 * @param teamDecl
@@ -650,7 +527,7 @@
 										    isGetter ?
 										    		fieldTypeRef
 										    :  		gen.typeReference(TypeBinding.VOID),
-										    getPrivateBridgeSelector(accessorSelector, roleName),
+										    SyntheticRoleBridgeMethodBinding.getPrivateBridgeSelector(accessorSelector, roleName),
 											isGetter ?
 													new Argument[] {
 										    			roleArg,
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/RoleTypeCreator.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/RoleTypeCreator.java
index f6662bd..9f1be43 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/RoleTypeCreator.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/RoleTypeCreator.java
@@ -327,7 +327,7 @@
         {
         	AbstractMethodDeclaration referenceMethod = scope.methodScope().referenceMethod();
         	if (referenceMethod != null)
-        		isCalloutGet &= (referenceMethod.isMappingWrapper == AbstractMethodDeclaration.WrapperKind.CALLOUT);
+        		isCalloutGet &= (referenceMethod.isMappingWrapper.callout());
         }
         if (!isCalloutGet) {
 	        if (refReturn instanceof WeakenedTypeBinding) {
@@ -533,8 +533,7 @@
 	    	MethodScope methodScope = scope.methodScope();
 	    	if (   methodScope != null
 	    		&& methodScope.referenceMethod() != null
-	    		&& methodScope.referenceMethod().isMappingWrapper
-	    				== AbstractMethodDeclaration.WrapperKind.CALLIN
+	    		&& methodScope.referenceMethod().isMappingWrapper._callin()
 //{OTDyn
 	    		&& !CallinImplementorDyn.DYNAMIC_WEAVING) // this heuristic doesn't work for dyn weaving, FIXME(SH): check if still needed!
 // SH}