Additional fixes re  Bug 324526 -  [reconciler] NPE during AST creation, team in role file subclassing non-team role
(cases where o.o.Team exists as source file in the workspace).
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
index b12b65f..fdc3fd6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
@@ -24,6 +24,7 @@
 import org.eclipse.jdt.internal.compiler.problem.*;
 import org.eclipse.jdt.internal.compiler.parser.*;
 import org.eclipse.jdt.internal.compiler.util.Util;
+import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.AbstractMethodMappingDeclaration;
 import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.AnchorListAttribute;
 import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.BytecodeTransformer;
@@ -484,15 +485,19 @@
 		        this,
 		        classFile,
 		        methodAttributeOffset);
+		boolean shouldRecordTeamMethod = false;
 		if (this.isMappingWrapper._callin()) {
 			AbstractMethodMappingDeclaration mapping = this.model._declaringMapping;
-			if (mapping != null && mapping.isCallin()) {
-				if (mapping.roleMethodSpec.isPrivate()) {
-					MethodModel methodModel = MethodModel.getModel(this);
-					methodModel.recordByteCode(classFile, methodAttributeOffset);
-				}
-			}
+			if (   mapping != null 
+				&& mapping.isCallin()
+				&& mapping.roleMethodSpec.isPrivate())
+				shouldRecordTeamMethod = true;
+		} else if (this.binding.declaringClass.id == IOTConstants.T_OrgObjectTeamsTeam) {
+			if (this.scope.environment().getTeamMethodGenerator().registerSourceMethodBytes(this.binding))
+				shouldRecordTeamMethod = true;
 		}
+		if (shouldRecordTeamMethod)
+			MethodModel.getModel(this).recordByteCode(classFile, methodAttributeOffset);
 	}
 // SH}	
 //{ObjectTeams: new hook
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
index 4c53343..f67677d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
@@ -834,9 +834,10 @@
 	// register byte code, evaluate attributes:
   } finally {
 	if (result != null && (method instanceof MethodInfo)) {
-		((MethodInfo)method).maybeRegister(this, result, this.environment);
 		if (TypeAnalyzer.isOrgObjectteamsTeam(this))
 			this.environment.getTeamMethodGenerator().registerTeamMethod(method, result);
+		// Note, that maybeRegister() may reset the MethodInfo (nulling MethodInfo.reference):
+		((MethodInfo)method).maybeRegister(this, result, this.environment);
 	}
   }
 // SH}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
index 60e598e..fb8d347 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
@@ -659,8 +659,10 @@
 				}
 			}
 		}
-		if (TypeAnalyzer.isOrgObjectteamsTeam(sourceType)) // handle the case of compiling org.objectteams.Team up front
+		if (TypeAnalyzer.isOrgObjectteamsTeam(sourceType)) {// handle the case of compiling org.objectteams.Team up front
 			this.referenceContext.adjustOrgObjectteamsTeam();
+			this.environment().getTeamMethodGenerator().registerOOTeamClass(sourceType);
+		}
 // SH}
 		checkAndSetModifiers();
 		buildTypeVariables();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/BytecodeTransformer.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/BytecodeTransformer.java
index 33ad74e..8ec1101 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/BytecodeTransformer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/BytecodeTransformer.java
@@ -113,8 +113,10 @@
         		&& !dstType.superclass.isTeam()) 
         	{
         		TeamMethodGenerator tmg = scope.environment().getTeamMethodGenerator();
-        		this._reader = new ConstantPoolObjectReader(tmg.classBytes, tmg.constantPoolOffsets, orgObjectteamsTeam.getTeamModel(), scope.environment());
-        		copyAllNonWideConstants(tmg.constantPoolOffsets.length, dstType.superclass, dstType);
+        		if (tmg.requestBytes()) { // if o.o.Team is converted we don't have the bytecode - and shouldn't need it
+        			this._reader = new ConstantPoolObjectReader(tmg.classBytes, tmg.constantPoolOffsets, orgObjectteamsTeam.getTeamModel(), scope.environment());
+        			copyAllNonWideConstants(tmg.constantPoolOffsets.length, dstType.superclass, dstType);
+        		}
         	}
 
         	TeamModel srcModel= dstType.superclass.getTeamModel();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/TeamMethodGenerator.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/TeamMethodGenerator.java
index f99eef6..b5afab1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/TeamMethodGenerator.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/TeamMethodGenerator.java
@@ -17,14 +17,13 @@
 package org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer;
 
 
+import static org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.AccFinal;
 import static org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.AccPrivate;
 import static org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.AccProtected;
 import static org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.AccPublic;
 import static org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.AccSynchronized;
-import static org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.AccFinal;
 import static org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers.AccVisibilityMASK;
 
-
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ClassFile;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
@@ -54,6 +53,8 @@
 import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.ConstantPoolObject;
 import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.ConstantPoolObjectMapper;
 import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.ConstantPoolObjectReader;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.RoleModel;
 import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstEdit;
@@ -141,16 +142,22 @@
 
 	// ==== Currently, this is where we globally store the byte code of org.objectteams.Team: ====
 	public byte[] classBytes;
-	public int headerOffset;
 	public int[] constantPoolOffsets;
+	// --- variant if o.o.Team is a SourceTypeBinding:
+	public SourceTypeBinding ooTeamBinding;
 	// ==== ====
 	
+    /** When binary methods for o.o.Team are created record the relevant method bindings. */
+    public void registerTeamMethod(IBinaryMethod method, MethodBinding methodBinding) {
+    	String selector = String.valueOf(method.getSelector());
+    	String descriptor = String.valueOf(method.getMethodDescriptor());
+		registerTeamMethod(methodBinding.declaringClass, methodBinding, selector, descriptor, -1/*structOffset not yet known*/);    	
+    }
 	/** When o.o.Team is read from .class file, record the byte code here. */
     public synchronized void maybeRegisterTeamClassBytes(ClassFileReader teamClass, ReferenceBinding teamClassBinding) {
     	if (this.classBytes != null)
     		return;
     	this.classBytes = teamClass.getBytes();
-    	this.headerOffset = teamClass.getHeaderOffset();
     	this.constantPoolOffsets = teamClass.getConstantPoolOffsets();
     	for (IBinaryMethod method : teamClass.getMethods()) {
     		if (this.classBytes == null && method instanceof MethodInfo) {
@@ -158,28 +165,64 @@
     			this.classBytes = ((MethodInfo)method).reference;
     			this.constantPoolOffsets = ((MethodInfo)method).constantPoolOffsets;
     		}
-			for (int s = 0; s < this.methodDescriptors.length; s++) {
-				if (   String.valueOf(method.getSelector()).equals(this.methodDescriptors[s].selector)
-					&& String.valueOf(method.getMethodDescriptor()).equals(this.methodDescriptors[s].signature))
-				{
-					this.methodDescriptors[s].methodCodeOffset = ((MethodInfo)method).getStructOffset();
-					this.methodDescriptors[s].declaringClass = teamClassBinding;
-					break;
-				}
-			}
+    		String selector = String.valueOf(method.getSelector());
+    		String descriptor = String.valueOf(method.getMethodDescriptor());
+    		int structOffset = ((MethodInfo)method).getStructOffset();
+    		// relevant new info is structOffset, everything has already  been registered from registerTeamMethod(IBinaryMethod,MethodBinding)
+    		registerTeamMethod(teamClassBinding, null, selector, descriptor, structOffset);
     	}
     }
-    /** When binary methods for o.o.Team are created record the relevant method bindings. */
-    public void registerTeamMethod(IBinaryMethod method, MethodBinding methodBinding) {
+	private boolean registerTeamMethod(ReferenceBinding declaringClass, MethodBinding methodBinding, String selector, String descriptor, int structOffset) {
 		for (int s = 0; s < this.methodDescriptors.length; s++) {
-			if (   String.valueOf(method.getSelector()).equals(this.methodDescriptors[s].selector)
-				&& String.valueOf(method.getMethodDescriptor()).equals(this.methodDescriptors[s].signature))
+			if (   selector.equals(this.methodDescriptors[s].selector)
+				&& descriptor.equals(this.methodDescriptors[s].signature))
 			{
-				this.methodDescriptors[s].binding = methodBinding;
-				break;
+				if (methodBinding != null)
+					this.methodDescriptors[s].binding = methodBinding;
+				this.methodDescriptors[s].declaringClass = declaringClass;
+				this.methodDescriptors[s].methodCodeOffset = structOffset;
+				return true;
 			}
-		}    	
+		}
+		return false;
+	}
+	// --- alternative initialization when compiling o.o.Team from source: ---
+    public synchronized void registerOOTeamClass(SourceTypeBinding ooTeamBinding) {
+    	if (this.classBytes != null)
+    		return;
+    	this.ooTeamBinding = ooTeamBinding;
     }
+	public boolean requestBytes() {
+		if (this.classBytes != null)
+			return true;
+		if (this.ooTeamBinding != null) {
+			if (isOOTConverted())
+				return false;
+			boolean result = Dependencies.ensureBindingState(this.ooTeamBinding, ITranslationStates.STATE_BYTE_CODE_GENERATED);
+			// the above causes callbacks to registerSourceMethodBytes(), info will be stored in corresponding MethodModels
+			// finish collecting info:
+			MethodModel model = this.methodDescriptors[0].binding.model;
+			this.classBytes = model.getBytes();
+			this.constantPoolOffsets = model.getConstantPoolOffsets();
+			return result;
+		}
+		return false; // shouldn't
+	}
+	boolean isOOTConverted() {
+		if (this.ooTeamBinding == null)
+			return false;
+		ClassScope scope = this.ooTeamBinding.scope;
+		if (scope == null)
+			return false;
+		TypeDeclaration typeDecl = scope.referenceContext;
+		return typeDecl.isConverted;
+	}
+	public boolean registerSourceMethodBytes(MethodBinding method) {
+		String selector = String.valueOf(method.selector);
+		String signature = String.valueOf(method.signature());
+		return registerTeamMethod(method.declaringClass, method, selector, signature, -1/*no structOffset before class is complete*/);
+	}
+	// ==============
     /** 
      * Add the AST representing all relevant methods and fields from o.o.Team,
      * and prepare methods for byte-code copy.
@@ -348,19 +391,34 @@
     	}
     	@Override
     	public void generateCode(ClassScope classScope, ClassFile classFile) {
+    		if (isOOTConverted())
+    			return; // don't actually try to generate, o.o.Team has no byte codes in this scenario
     		this.binding.copyInheritanceSrc = this.descriptor.binding;
     		ConstantPoolObjectMapper mapper = new TeamConstantPoolMapper(this.descriptor.binding, this.binding);
-    		ConstantPoolObjectReader reader = new ConstantPoolObjectReader( TeamMethodGenerator.this.classBytes, 
-    																		TeamMethodGenerator.this.constantPoolOffsets, 
+    		byte[] bytes;
+    		int[] offsets;
+    		int structOffset;
+    		if (this.descriptor.methodCodeOffset == -1) {
+    			MethodModel srcModel = this.descriptor.binding.model;
+    			bytes        = srcModel.getBytes();
+    			offsets      = srcModel.getConstantPoolOffsets();
+    			structOffset = srcModel.getStructOffset();
+    		} else {
+    			bytes        = TeamMethodGenerator.this.classBytes;
+    			offsets      = TeamMethodGenerator.this.constantPoolOffsets;
+    			structOffset = this.descriptor.methodCodeOffset;
+    		}
+			ConstantPoolObjectReader reader = new ConstantPoolObjectReader( bytes, 
+    																		offsets, 
     																		this.descriptor.declaringClass.getTeamModel(), 
     																		this.scope.environment());
-			new BytecodeTransformer().doCopyMethodCode( null /*srcRoleModel*/, this.binding, 								// source
-    													(SourceTypeBinding)this.binding.declaringClass, this, 				// destination
-    													TeamMethodGenerator.this.classBytes, 				 				// source bytes
-    													TeamMethodGenerator.this.constantPoolOffsets,
-    													this.descriptor.methodCodeOffset,
-    													reader, mapper,														// mapping strategies 
-    													classFile);															// final destination
+			new BytecodeTransformer().doCopyMethodCode( null /*srcRoleModel*/, this.binding, 					// source
+    													(SourceTypeBinding)this.binding.declaringClass, this, 	// destination
+    													bytes, 				 									// source bytes
+    													offsets,
+    													structOffset,
+    													reader, mapper,											// mapping strategies 
+    													classFile);												// final destination
     	}
     }