/**********************************************************************
 * This file is part of "Object Teams Dynamic Runtime Environment"
 * 
 * Copyright 2009, 2019 Oliver Frank 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.eclipse.org/objectteams for updates and contact.
 * 
 * Contributors:
 *		Oliver Frank - Initial API and implementation
 *		Stephan Herrmann - Initial API and implementation
 **********************************************************************/
package org.eclipse.objectteams.otredyn.bytecode;

import java.lang.instrument.IllegalClassFormatException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.eclipse.objectteams.otredyn.runtime.ClassIdentifierProviderFactory;
import org.eclipse.objectteams.otredyn.runtime.IBinding;
import org.eclipse.objectteams.otredyn.runtime.IBoundClass;
import org.eclipse.objectteams.otredyn.runtime.IMethod;
import org.eclipse.objectteams.otredyn.runtime.TeamManager;
import org.eclipse.objectteams.otredyn.runtime.ISubclassWiringTask;
import org.eclipse.objectteams.otredyn.transformer.IWeavingContext;
import org.eclipse.objectteams.runtime.IReweavingTask;
import org.objectweb.asm.Opcodes;

import org.eclipse.jdt.annotation.*;

/**
 * This class represents a java class.
 * It stores the information about a class parsed from the bytecode and
 * it handles callin and decapsulation bindings for the class
 * @author Oliver Frank
 */
public abstract class AbstractBoundClass implements IBoundClass {
	
	private static enum WeavingTaskType {
		WEAVE_BINDING_OF_SUBCLASS,
		WEAVE_BINDING,
		/**
		 * Weaving of bindings for overridden methods whose super version is callin-bound.
		 * Includes replacement of "wicked super calls" towards those bound super methods.
		 */
		WEAVE_INHERITED_BINDING,
		WEAVE_METHOD_ACCESS,
		WEAVE_FIELD_ACCESS,
		WEAVE_INHERITED_MEMBER_ACCESS,
		WEAVE_BASE_INFRASTRUCTURE
	}

	/**
	 * A structure that is internally used to store which methods are still woven
	 * and which has to be woven.
	 */
	private static class WeavingTask {
		
		private WeavingTaskType weavingTaskType;
		private String memberName;
		private String memberSignature;
		private String memberPrefixId;
		private int baseFlags;
		private boolean doAllTransformations;
		private boolean isHandleCovariantReturn;
		private boolean requireBaseSuperCall;

		public WeavingTask(WeavingTaskType weavingTaskType, String memberName, String memberSignature, int baseFlags, boolean handleCovariantReturn, boolean requireBaseSuperCall) {
			this.weavingTaskType = weavingTaskType;
			this.memberName = memberName;
			this.memberSignature = memberSignature;
			this.isHandleCovariantReturn = handleCovariantReturn;
			this.requireBaseSuperCall = requireBaseSuperCall;
			this.baseFlags = baseFlags;
		}
		
		public WeavingTask(WeavingTaskType weavingTaskType, Method method, WeavingTask upstream, AbstractBoundClass upstreamClass) {
			this(weavingTaskType, method.getName(), method.getSignature(),
					upstream.getBaseFlags(), upstream.isHandleCovariantReturn(), false);
			if (weavingTaskType == WeavingTaskType.WEAVE_INHERITED_BINDING
					&& upstream != null && ((upstream.getBaseFlags() & IBinding.PRIVATE_BASE) != 0)
					&& upstreamClass != null)
				this.memberPrefixId = upstreamClass.getId();
		}

		public WeavingTask(WeavingTaskType type) {
			this(type, null, null, 0, false, false);
		}

		/**
		 * Returns the type of the WeavingTask
		 * @return
		 */
		public WeavingTaskType getType() {
			return weavingTaskType;
		}
		
		/**
		 * Returns the name of the member, that has to be woven
		 * @return
		 */
		public String getMemberName() {
			return memberName;
		}

		/**
		 * Returns the signature of the member, that has to be woven
		 * @return
		 */
		public String getMemberSignature() {
			return memberSignature;
		}
		
		public String getMethodIdentifier(AbstractBoundClass clazz) {
			String prefix = memberPrefixId != null ? memberPrefixId : clazz.getId();
			int close = this.memberSignature.lastIndexOf(')');
			return prefix + '.' + this.memberName + this.memberSignature.substring(0, close+1);
		}

		public int getBaseFlags() {
			return baseFlags;
		}
		
		/**
		 * This information is only needed for callin bindings.
		 * @return If true, all transformation has to be done, if false,
		 * only callAllBindings has to be redefined
		 */
		public boolean doAllTransformations() {
			return doAllTransformations;
		}

		public void setDoAllTransformations(boolean doAllTransformations) {
			this.doAllTransformations = doAllTransformations;
		}

		public boolean isHandleCovariantReturn() {
			return this.isHandleCovariantReturn;
		}

		public boolean requiresBaseSuperCall() {
			return this.requireBaseSuperCall;
		}

		@Override
		public String toString() {
			StringBuilder buf = new StringBuilder();
			buf.append(this.weavingTaskType).append(": ");
			if (this.memberPrefixId != null)
				buf.append(this.memberPrefixId).append('-');
			buf.append(this.memberName).append(this.memberSignature);
			return buf.toString();
		}
	}

	// completed WeavingTasks for callin bindings mapped by the method,
	// that was woven
	private Map<Method, WeavingTask> completedBindingTasks;
	
	// not completed WeavingTasks for callin bindings mapped by the method,
	// that has to be woven
	public Map<Method, WeavingTask> openBindingTasks; // NB: this map is used as the monitor for itself & openAccessTasks.
	
	// completed WeavingTasks for decapsulation bindings mapped by the member,
	// that was woven
	private Map<Member, WeavingTask> completedAccessTasks;
	
	// open WeavingTasks for decapsulation bindings mapped by the member,
	// that has to be woven
	private Map<Member, WeavingTask> openAccessTasks;
	
	private List<ISubclassWiringTask> wiringTasks;

	// while > 0 we are batching modifications before executing handleTaskList()
	protected int transactionCount;

	protected boolean parsed;

	//FQN (e.g. "foo.bar.MyClass")
	private @NonNull String name;
	
	//internal FQN (e.g. "foo/bar/MyClass.class")
	private String internalName;
	
	// A globally unique identifier for the class
	private String id;
	private String superClassName;
	private String internalSuperClassName;
	private String[] internalSuperInterfaces;
	private AbstractBoundClass superclass;
	private AbstractBoundClass enclosingClass;
	private Map<String, Method> methods;
	private Map<String, Field> fields;
	protected Map<AbstractBoundClass, Object> subclasses;
	
	// Is the java class, that was represented by the AbstractBoundClass
	// already loaded by a class loader or not
	private boolean isLoaded;
	protected boolean isUnweavable;

	/** Within one base hierarchy, callOrig and callAllBindings may need to propagate to supers. */
	protected boolean hierarchyIsCallinAffected = false;
	
	private int modifiers;

	private int otClassFlags;
	private boolean implicitTeamActivationEnabled = false;
	private Set<String> methodsForImplicitActivation;

	protected ClassLoader loader;

	// callback
	protected IWeavingContext weavingContext;

	@Nullable
	protected Class<?> definedClass;


	/**
	 * No public constructor, beacause only the ClassRepository should
	 * create AbstractBoundClasses
	 * @param name dot-separated class name
	 * @param id unique identifier, able to differentiate same-named classes from different classloaders
	 * @param loader classloader responsible for loading this class
	 */
	protected AbstractBoundClass(@NonNull String name, String id, ClassLoader loader) {
//		if (name.indexOf('/')!= -1)
//			new RuntimeException(name).printStackTrace(System.out);
		this.name = name;
		this.internalName = name.replace('.', '/');
		this.id = id;
		this.loader = loader;
		completedBindingTasks = new IdentityHashMap<Method, WeavingTask>();
		openBindingTasks = new IdentityHashMap<Method, WeavingTask>();
		openAccessTasks = new IdentityHashMap<Member, WeavingTask>();
		completedAccessTasks = new IdentityHashMap<Member, WeavingTask>();
		methods = new HashMap<String, Method>();
		fields = new HashMap<String, Field>();
		subclasses = new IdentityHashMap<AbstractBoundClass, Object>();
		
		// don't fetch a anonymous subclass for a anonymous subclass
		if (!name.equals(ClassRepository.ANONYMOUS_SUBCLASS_NAME)) {
			AbstractBoundClass anonymousSubclass = ClassRepository
					.getInstance().getAnonymousSubclass(this);
			subclasses.put(anonymousSubclass, null);
		}
	}

	/**
	 * Returns the name of the Class
	 * @return
	 */
	public @NonNull String getName() {
		return name;
	}

	public String getId() {
		return id;
	}

	public boolean isAnonymous() {
		return getName().equals(ClassRepository.ANONYMOUS_SUBCLASS_NAME);
	}
	
	/**
	 * Returns the classloader responsible for loading this class.
	 * @return
	 */
	public ClassLoader getClassLoader() {
		return this.loader;
	}
	
	/**
	 * Set the name of the super class of this class
	 * @param superClassName
	 */
	public void setSuperClassName(String superClassName) {
		if (superClassName == null) {
			return;
		}
		this.superClassName = superClassName.replace('/', '.');
		this.internalSuperClassName = superClassName.replace('.', '/');
	}

	public void setSuperInterfaces(String[] interfaces) {
		if (interfaces == null)
			return;
		this.internalSuperInterfaces = interfaces;
	}

	public boolean isJavaLangObject() {
		return this.name.equals("java.lang.Object");
	}

	/**
	 * Is the class a interface?
	 * @return
	 */
	public boolean isInterface() {
		parseBytecode();
		return (this.modifiers & Opcodes.ACC_INTERFACE) != 0;
	}
	
	/**
	 * Does this AbstractBoundClass represents a Team.
	 * @return if true, the method getTeam of the ClassRepository 
	 * could be called to get an instance of AbstractTeam 
	 */
	public boolean isTeam() {
		parseBytecode();
		return (this.otClassFlags & Types.TEAM_FLAG) != 0;
	}
	
	/**
	 * Number of outer instances required in an instance of this class.
	 */
	public int nestingDepth() {
		parseBytecode();
		if ((this.modifiers & Opcodes.ACC_STATIC) != 0)
			return 0;
		if (this.enclosingClass != null)
			return this.enclosingClass.nestingDepth()+1;
		return 0;
	}

	/**
	 * Store class modifiers (incl. visibility, AccStatic, AccInterface, AccStatic
	 */
	public void setModifiers(int modifiers) {
		this.modifiers = modifiers;
	}

	public void setOTClassFlags(int flags) {
		this.otClassFlags = flags;		
	}
	
	public boolean isRole() {
		return (this.otClassFlags & Types.ROLE_FLAG) != 0;
	}

	public boolean isProtected() {
		return (this.modifiers & Opcodes.ACC_PROTECTED) != 0;
	}

	public void enableImplicitActivation() {
		this.implicitTeamActivationEnabled = true;		
	}

	public void registerMethodForImplicitActivation(String methodNameAndDesc) {
		if (this.methodsForImplicitActivation == null)
			this.methodsForImplicitActivation = new HashSet<String>();
		this.methodsForImplicitActivation.add(methodNameAndDesc);
	}

	public boolean hasMethodImplicitActivation(String methodNameAndDesc, boolean methodIsAccessible) {
		if (this.implicitTeamActivationEnabled && methodIsAccessible) // for all accessible methods
			return true;
		if (this.methodsForImplicitActivation == null)
			return false;
		return this.methodsForImplicitActivation.contains(methodNameAndDesc);
	}

	public void setWeavingContext(IWeavingContext weavingContext) {
		this.weavingContext = weavingContext;
	}

	/**
	 * Do all needed transformations needed at load time:
	 * Add the interface IBoundBase2
	 * Add the empty method callOrig
	 * Add the empty method callOrigStatic
	 * Add the empty method access
	 * Add the empty method accessStatic
	 * Add the empty method callAllBindings
	 * @throws IllegalClassFormatException various bytecode problems, e.g., unexpected RET instruction etc.
	 */
	public void transformAtLoadTime() throws IllegalClassFormatException {
		handleTaskList(null);
	}

	/**
	 * Mark as loaded
	 */
	public void setLoaded() {
		this.isLoaded = true;
	}
	
	/**
	 * Returns an instance of AbstractBoundClass that represents 
	 * the super class of this class.
	 * It parses the bytecode, if that has not already been done 
	 * @return an instance of AbstractBoundClass that represents 
	 * the super class of this class
	 */
	public AbstractBoundClass getSuperclass() {
		if (superclass == null) {
			synchronized (this) {
				parseBytecode();
				String checkedSuperClassName = superClassName;
				if (checkedSuperClassName != null && superclass == null) {
					String superclassId = ClassIdentifierProviderFactory.getClassIdentifierProvider().getSuperclassIdentifier(id, internalSuperClassName);
					
					//if superclassId is null the class could be "Object" or an interface
					if (superclassId != null) {
						superclass = ClassRepository.getInstance().getBoundClass(checkedSuperClassName, superclassId, loader);
						superclass.addSubclass(this);
						// FIXME(SH): can we avoid adding all subclasses to j.l.Object?
					}
				}
			}
		}
		return superclass;
	}
	
	/**
	 * Returns the internal names of all superInterfaces or null.
	 */
	public /*@Nullable*/ String[] getSuperInterfaceNames() {
		parseBytecode();
		return this.internalSuperInterfaces;
	}

	/**
	 * Returns an instance of AbstractBoundClass that represents 
	 * the enclosing class of this class.
	 * It parses the bytecode, if that has not already been done 
	 * @return an instance of AbstractBoundClass that represents 
	 * the enclosing class of this class
	 */
	public synchronized AbstractBoundClass getEnclosingClass() {
		parseBytecode();
		int pos = this.internalName.lastIndexOf('$');
		if (pos != -1) {
			String enclosingClassName = this.internalName.substring(0, pos); 
			// FIXME(SH): do we need a new getEnclosingClassIdentifier?
			String enclosingClassID = ClassIdentifierProviderFactory.getClassIdentifierProvider().getSuperclassIdentifier(id, enclosingClassName);
			
			if (enclosingClassID != null) {
				enclosingClass = ClassRepository.getInstance().getBoundClass(enclosingClassName, enclosingClassID, loader);
				enclosingClass.addSubclass(this);
			}
		}
		return enclosingClass;
	}

	public synchronized String getEnclosingClassName() {
		parseBytecode();
		int pos = this.internalName.lastIndexOf('$');
		if (pos != -1) {
			return this.internalName.substring(0, pos); 
		}
		return null;
	}

	/**
	 * This method parses the bytecode, if that has not already been done 
	 */
	public abstract void parseBytecode();
	
	/**
	 * Returns the internal name of the super class of this class
	 * It parses the bytecode, if that has not already been done
	 * @return
	 */
	public String getInternalSuperClassName() {
		parseBytecode();
		return internalSuperClassName;
	}

	/**
	 * Returns the internal name of the super class of this class IFF that super class is weavable,
	 * otherwise it returns {@code null}.
	 * It parses the bytecode, if that has not already been done
	 * @return
	 */
	public String getInternalWeavableSuperClassName(boolean considerSupers) {
		if (!isSuperWeavable(considerSupers))
			return null;
		parseBytecode();
		return internalSuperClassName;
	}

	protected abstract boolean isSuperWeavable(boolean considerSupers);

	/**
	 * Returns the internal name of this class
	 * @return
	 */
	public String getInternalName() {
		return internalName;
	}
	
	/**
	 * Returns the name of the super class of this class
	 * It parses the bytecode, if that has not already been done
	 * @return
	 */
	public String getSuperClassName() {
		parseBytecode();
		return superClassName;
	}

	/**
	 * Adds a method to this class.
	 * This method is intended to be called, 
	 * while parsing the bytecode
	 * @param name the name of the field
	 * @param desc the signature of the method
	 * @param isStatic is this method static
	 * @param isPrivate is this method private
	 */
	public void addMethod(String name, String desc, boolean isStatic, int accessFlags) {
		if (desc == null) {
			System.err.println("OTDRE: Method "+name+" in class "+this.name+" has no descriptor");
			return;
		}
		String methodKey = getMethodKey(name, desc);
		Method method = methods.get(methodKey);
		// Does this method already exists?
		// Methods are created by getMethod, if the class is not loaded
		if (method == null) {
			method = new Method(name, desc, isStatic, accessFlags);
			method.setImplemented(true);
			methods.put(methodKey, method);
		} else {
			// Yes, so set additional information.
			method.setImplemented(true);
			method.setStatic(isStatic);
		}
	}

	/** Method signature sans the return type. */
	private String getMethodKey(String name, String desc) {
		int pos = desc.indexOf(')');
		return name+desc.substring(0,pos+1);
	}

	/**
	 * Adds a field to this class.
	 * This method is intended to be called, 
	 * while parsing the bytecode
	 * @param name the name of the field
	 * @param desc the signature of the field
	 * @param isStatic is this field static
	 * @param accessFlag ACC_PUBLIC, ACC_PROTECTED, ACC_PRIVATE or 0.
	 */
	public void addField(String name, String desc, boolean isStatic, int accessFlags) {
		Field field = fields.get(name);
		if (field == null) {
			field = new Field(name, desc, isStatic, accessFlags);
			fields.put(name, field);
		} else {
			field.setStatic(isStatic);
		}
	}

	public Method getMethod(String name, String desc, int flags, boolean allowCovariantReturn) {
		if (this.parsed) {
			// in this state the current class may already be inside synchronized handleTaskList(), try without lock:
			String methodKey = getMethodKey(name, desc);
			Method method = methods.get(methodKey);
			if (method != null) {
				if (allowCovariantReturn || method.getSignature().equals(desc))
					return method;
				return null;
			}
		}
		synchronized(this) {
			parseBytecode();
			String methodKey = getMethodKey(name, desc);
			Method method = methods.get(methodKey);
			if (!allowCovariantReturn && method != null && !method.getSignature().equals(desc))
				return null; // don't use this
			if (method == null) {
				// class was not yet loaded
				int access = 0;
				if ((flags&IBinding.PRIVATE_BASE) != 0)
					access |= Opcodes.ACC_PRIVATE;
				else if ((flags&IBinding.PUBLIC_BASE) != 0)
					access |= Opcodes.ACC_PUBLIC;
				method = new Method(name, desc, ((flags&IBinding.STATIC_BASE) != 0), access);
				methods.put(methodKey, method);
			}
			return method;
		}
	}
	
	Method getMethod(WeavingTask task) {
		return getMethod(task.getMemberName(), task.getMemberSignature(), task.getBaseFlags(), task.isHandleCovariantReturn());
	}

	Method getMethod(Method method, WeavingTask task) {
		return getMethod(method.getName(), method.getSignature(), task.getBaseFlags(), task.isHandleCovariantReturn());
	}

	// same as above but specifically request a static/non-static method
	public synchronized Method getMethod(String name, String desc, boolean allowCovariantReturn, boolean isStatic) {
		parseBytecode();
		String methodKey = getMethodKey(name, desc);
		Method method = methods.get(methodKey);
		if (!allowCovariantReturn && method != null && !method.getSignature().equals(desc))
			method = null; // don't use this
		if (method == null) {
			// class was not yet loaded
			method = new Method(name, desc);
			method.setStatic(isStatic);
			methods.put(methodKey, method);
		}
		boolean actualStatic = method.isStatic();
		if (name.equals("<init>"))
			actualStatic = true; // see OTSpecialAccessAttribute.readMethodAccess(..) re static accessor
		assert actualStatic == isStatic : "Mismatching static/non-static methods "+getName()+'.'+name+desc;
		return method;
	}

	public synchronized Field getField(String name, String desc) {
		parseBytecode();
		Field field = fields.get(name);
		if (field == null) {
			// class was not yet loaded
			field = new Field(name, desc);
			fields.put(name, field);
		}
		return field;
	}


	public String getMethodIdentifier(IMethod method) {
		String signature = method.getSignature();
		int close = signature.lastIndexOf(')'); // admit covariant return
		return getId() + '.' + method.getName() + signature.substring(0, close+1);
	}

	/**
	 * Adds a subclass to this class
	 * @param subclass
	 */
	protected void addSubclass(AbstractBoundClass subclass) {
		subclasses.put(subclass, null);
	}

	/**
	 * Remove subclass from this class. It's only needed
	 * to remove a anonymous subclass, if a real subclass is loaded
	 * @param subclass
	 */
	protected void removeSubclass(AbstractBoundClass subclass) {
		subclasses.remove(subclass);
	}

	/**
	 * Returns all subclasses of this class, 
	 * including the anonymous subclass
	 * @return
	 */
	private Collection<AbstractBoundClass> getSubclasses() {
		return new ArrayList<AbstractBoundClass>(subclasses.keySet());
	}

	/**
	 * Handle all open weaving tasks for this class.
	 * It redefines the class, if it is not called while loading
	 * @param definedClass previously defined class if available
	 * @throws IllegalClassFormatException various bytecode problems, e.g., unexpected RET instruction etc.
	 */
	public void handleTaskList(@Nullable Class<?> definedClass) throws IllegalClassFormatException {
		if (this.definedClass == null && definedClass != null)
			this.definedClass = definedClass;
		if (isTransformationActive()) return;

		if (this.isUnweavable)
			new LinkageError("Class "+this.name+" is requested to be woven, but it is marked as unweavable.").printStackTrace();

		synchronized(this) {
			boolean firstIteration = true;
			while (true) {
				boolean processingOpenTasks = false;
				Set<Map.Entry<Method, WeavingTask>> bindingEntrySet;
				Set<Map.Entry<Member, WeavingTask>> accessEntrySet;
				synchronized (openBindingTasks) {
					bindingEntrySet = copyEntrySet(openBindingTasks);
					accessEntrySet = copyEntrySet(openAccessTasks);
					processingOpenTasks = !openBindingTasks.isEmpty() || !openAccessTasks.isEmpty();
					if (processingOpenTasks) {
						openBindingTasks.clear();
						openAccessTasks.clear();
					} else {
						if (!firstIteration)
							break; // executed at least once and have not received more open tasks since previous
					}
				}
				firstIteration = false;
		
				// Are there not handled callin or decapsulation bindings 
				// for this class
				if (bindingEntrySet.size() > 0 || accessEntrySet.size() > 0) {
					// Yes, so start the transformation, parse the bytecode
					// and do load time transforming, if this method is called
					// at load time
					startTransformation();
					parseBytecode();
					prepareAsPossibleBaseClass();
					prepareTeamActivation();
					prepareLiftingParticipant();
				} else if (isFirstTransformation()) {
					// No, so only do load time transforming, if this method is called
					// at load time
					startTransformation();
					prepareAsPossibleBaseClass();
					if (hierarchyIsCallinAffected()) {
						createSuperCalls();
					}
					prepareTeamActivation();
					prepareLiftingParticipant();
					endTransformation(definedClass);
				}
		
				// collect other classes for which new tasks are recorded, to flush those tasks in bulk at the end
				Set<AbstractBoundClass> affectedClasses = new HashSet<AbstractBoundClass>();
		
				for (Map.Entry<Method, WeavingTask> entry : bindingEntrySet) {
					WeavingTask task = entry.getValue();
					Method method = entry.getKey();
					switch (task.getType()) {
					// Weave callin binding to a method of a subclass, that is not implemented
					// in the subclass
					case WEAVE_BINDING_OF_SUBCLASS:
						// Is the method implemented in this class?
						if (method.isImplemented()) {
							// Yes, so weave this class
							weaveBindingOfSubclass(task);
						} else {
							//No, so just delegate the weaving task to the superclass
							AbstractBoundClass superclass = getSuperclass();
							// If superclass is null, there is something wrong
							if (superclass != null) {
								superclass.addWeavingTask(task, true/*standBy*/);
								affectedClasses.add(superclass);
								weaveSuperCallInCallOrig(task); // ensure we're actually calling that super version
							}
						}
						break;
					// Weave callin binding to a method of this class
					case WEAVE_BINDING:
						if (method.isStatic()) {
							weaveBindingInStaticMethod(task);
						} else {
							// Is the method implemented in this class?
							if (method.isImplemented()) {
								// So redefine the method
								weaveBindingInImplementedMethod(task);
								if (!method.isStatic() && weavingContext.isWeavable(getSuperClassName(), false, false)) {
									AbstractBoundClass superclass = getSuperclass();
									Method superMethod = superclass.getMethod(method.getName(), method.getSignature(), true, false);
									if (superMethod.isImplemented()) {
										// binding affects also the super implementation, need to handle wicked super calls:
										replaceWickedSuperCalls(getSuperclass(), method);
									}
								}
							} else {
								// No, so weave this class and delegate to the implementing super class
								weaveBindingInNotImplementedMethod(task, true);
								AbstractBoundClass superclass = getSuperclass();
								while (superclass != null && !superclass.isJavaLangObject()) {
									if (weavingContext.isWeavable(superclass.getName(), false, false)) { // explicitly traversing supers
										Method superMethod = superclass.getMethod(method, task);
										if (superMethod != null) {
											WeavingTask newTask = new WeavingTask(WeavingTaskType.WEAVE_BINDING_OF_SUBCLASS, superMethod, task, null);
											superclass.addWeavingTask(newTask, true/*standBy*/);
											affectedClasses.add(superclass);
											break;
										}
									}
									superclass = superclass.getSuperclass();
								}
							}
		
		// Original comment:
		//   If this method is private, the callin binding is not
		//   inherited by the subclasses
		// However, this conflicts with test415_nonexistingBaseMethod3i,
		// where an empty callAllBindings() was overriding a non-empty one.
		// see also Method.getId()
		//					if (!method.isPrivate()) {
								// Delegate the WeavingTask to the subclasses
								for (AbstractBoundClass subclass : getSubclasses()) {
									Method subMethod = subclass.getMethod(method, task);
									if (subMethod != null) {
										WeavingTask newTask = new WeavingTask(WeavingTaskType.WEAVE_INHERITED_BINDING, subMethod, task, this);
										subclass.addWeavingTask(newTask, true/*standBy*/);
										affectedClasses.add(subclass);
										TeamManager.mergeJoinpoints(this, subclass, method, subMethod, task.isHandleCovariantReturn());
									}
								}
		//					}
						}
						break;
					// Weave Binding inherited from the superclass
					case WEAVE_INHERITED_BINDING:
						if (method.isImplemented()) {
							weaveBindingInImplementedMethod(task);
							if (!method.isStatic()) {
								replaceWickedSuperCalls(getSuperclass(), method);
							}
						} else {
							weaveBindingInNotImplementedMethod(task, false);
						}
		
						// Delegate the WeavingTask to the subclasses
						for (AbstractBoundClass subclass : getSubclasses()) {
							Method subMethod = subclass.getMethod(method, task);
							WeavingTask newTask = new WeavingTask(WeavingTaskType.WEAVE_INHERITED_BINDING, subMethod, task, this);
							subclass.addWeavingTask(newTask, true/*standBy*/);
							affectedClasses.add(subclass);
							TeamManager.mergeJoinpoints(this, subclass, method, subMethod, task.isHandleCovariantReturn());
						}
		
						break;
					}
					
					// Mark all WeavingTasks for callin bindings 
					// as completed
					completedBindingTasks.put(method, task);
				}
				
				//handle all WeavinTasks for decapsulation bindings
				for (Map.Entry<Member, WeavingTask> entry : accessEntrySet) {
					WeavingTask task = entry.getValue();
					Member member = entry.getKey();
					
					switch (task.getType()) {
					// handle decapsulation binding to a field
					case WEAVE_FIELD_ACCESS:
						prepareForFirstMemberAccess();
						Field field = getField(task.getMemberName(), task
								.getMemberSignature());
						weaveFieldAccess(field, field.getGlobalId(this));
						if (!field.isStatic()) {
							// If the field is not static it could be accessed through a subclass
							// so weave the subclass
							for (AbstractBoundClass subclass : getSubclasses()) {
								WeavingTask newTask = new WeavingTask(WeavingTaskType.WEAVE_INHERITED_MEMBER_ACCESS);
								subclass.addWeavingTask(newTask, true/*standBy*/);
								affectedClasses.add(subclass);
							}
						}
						break;
					// handle decaspulation binding to a method
					case WEAVE_METHOD_ACCESS:
						prepareForFirstMemberAccess();
						Method method = getMethod(task);
						weaveMethodAccess(method, method.getGlobalId(this));
						if (!method.isStatic()) {
							// If the method is not static it could be accessed through a subclass
							// so weave the subclass
							for (AbstractBoundClass subclass : getSubclasses()) {
								WeavingTask newTask = new WeavingTask(WeavingTaskType.WEAVE_INHERITED_MEMBER_ACCESS);
								subclass.addWeavingTask(newTask, true/*standBy*/);
								affectedClasses.add(subclass);
							}
						}
						break;
					case WEAVE_INHERITED_MEMBER_ACCESS:
						prepareForFirstMemberAccess();
						break;
					case WEAVE_BASE_INFRASTRUCTURE:
						prepareForFirstTransformation();
						break;
					}
					
					// Mark all WeavingTasks for decapsulation bindings 
					// as completed
					completedAccessTasks.put(member, task);
				}
				// flush collected tasks of other affected classes:
				for (final AbstractBoundClass affected : affectedClasses)
					if (affected.isLoaded) {
						IReweavingTask task = new IReweavingTask() {
							@Override public void reweave(@Nullable Class<?> definedClass) throws IllegalClassFormatException {
								affected.handleTaskList(definedClass);
							}
						};
						if (!weavingContext.scheduleReweaving(affected.name, task))
							affected.handleTaskList(definedClass);
					}
		
				if (processingOpenTasks) {
					// Weave the class, if the method is not called at load time
					endTransformation(definedClass);
				}
			}
		}
		// after releasing the lock:
		superTransformation(definedClass);
	}

	protected abstract void createSuperCalls();
	protected abstract void propagateCallinInfraToSubclasses();

	private boolean hierarchyIsCallinAffected() {
		if (this.hierarchyIsCallinAffected)
			return true;
		AbstractBoundClass zuper = getSuperclass();
		if (zuper != null && !zuper.isJavaLangObject()) {
			if (zuper.hierarchyIsCallinAffected())
				return this.hierarchyIsCallinAffected = true;
		}
		return false;
	}

	<K,V> Set<Entry<K, V>> copyEntrySet(Map<K,V> map) {
		if (map.isEmpty()) return Collections.emptySet();
		Map<K, V> bindingMap = new HashMap<K, V>();
		for (Entry<K, V> entry : map.entrySet())
			bindingMap.put(entry.getKey(), entry.getValue());
		return bindingMap.entrySet();
	}

	public void handleAddingOfBinding(IBinding binding) {
		WeavingTaskType type = null;
		WeavingTask task = null;
		switch (binding.getType()) {
		case CALLIN_BINDING:
			type = WeavingTaskType.WEAVE_BINDING;
			break;
		case FIELD_ACCESS:
			type = WeavingTaskType.WEAVE_FIELD_ACCESS;
			break;
		case METHOD_ACCESS:
			type = WeavingTaskType.WEAVE_METHOD_ACCESS;
			break;
		case ROLE_BASE_BINDING:
			task = new WeavingTask(WeavingTaskType.WEAVE_BASE_INFRASTRUCTURE);
			break;
		default:
			throw new RuntimeException("Unknown binding type: "
					+ binding.getType().name());
		}
// TODO: once needed for test4141_dangerousCallinBinding3, but no longer.
// Instead it causes the need to redefine classes in OT/Equinox, hence disabled.
//		if (   binding.getType() == IBinding.BindingType.CALLIN_BINDING 
//			&& !binding.getBoundClass().equals(binding.getDeclaringBaseClassName()))
//			try {
//				// need to load the declaring base class outside the transform() callback:
//				this.loader.loadClass(binding.getDeclaringBaseClassName().replace('/', '.'));
//			} catch (ClassNotFoundException e) {
//				throw new NoClassDefFoundError(e.getMessage());
//			}
		if (task == null)
			task = new WeavingTask(type, binding.getMemberName(), binding.getMemberSignature(), 
											binding.getBaseFlags(), binding.isHandleCovariantReturn(), binding.requiresBaseSuperCall());
		try {
			addWeavingTask(task, false);
		} catch (IllegalClassFormatException e) {
			e.printStackTrace(); // we're called from TeamManager, which can neither log nor handle exceptions
		}
	}
	
	@Override
	public synchronized void startTransaction() {
		this.transactionCount ++;
	}

	@Override
	public synchronized void commitTransaction(@Nullable Class<?> definedClass) {
		--this.transactionCount;
		if (this.transactionCount == 0 && this.isLoaded) {
			try {
				handleTaskList(definedClass);
			} catch (IllegalClassFormatException e) {
				e.printStackTrace(); // we're called from TeamManager, which can neither log nor handle exceptions
			}
		}
	}
	
	private void addWeavingTask(WeavingTask task, boolean standBy) throws IllegalClassFormatException {
		boolean isNewTask = addWeavingTaskLazy(task);

		if (this.isLoaded && isNewTask && !standBy && this.transactionCount == 0) {
			handleTaskList(null);
		}
	}
	
	private boolean addWeavingTaskLazy(WeavingTask task) {
		WeavingTaskType type = task.getType();
		boolean isNewTask = false;
		if (type == WeavingTaskType.WEAVE_BINDING
				|| type == WeavingTaskType.WEAVE_BINDING_OF_SUBCLASS
				|| type == WeavingTaskType.WEAVE_INHERITED_BINDING) {
			isNewTask = addBindingWeavingTask(task);
		} else {
			isNewTask = addAccessWeavingTask(task);
		}
		
		return isNewTask;
	}

	/**
	 * Handle a new WeavingTask for decapsulation and 
	 * figures out if weaving is needed for this task 
	 * @param task
	 * @return
	 */
	private boolean addAccessWeavingTask(WeavingTask task) {
		WeavingTaskType type = task.getType();
		Member member = null;
		switch (type) {
		case WEAVE_FIELD_ACCESS:
			member = getField(task.getMemberName(), task.getMemberSignature());
			break;
		case WEAVE_METHOD_ACCESS:
			member = getMethod(task);
			break;
			// switch "continued" inside the synchronized block:
		}
		synchronized (this.openBindingTasks) { // sic: openBindingTasks is used as the monitor for both maps
			switch (type) {
			case WEAVE_INHERITED_MEMBER_ACCESS:
			case WEAVE_BASE_INFRASTRUCTURE:
				openAccessTasks.put(null, task);
				return true;
			}
			if (member == null) return false;
			
			synchronized (member) {
				WeavingTask prevTask = completedAccessTasks.get(member);
				// Is there a already completed task for the member?
				if (prevTask == null) {
					// No, so check the open tasks
					prevTask = openAccessTasks.get(member);
				}
				
				// Is there a open task for the member?
				if (prevTask == null) {
					// No, so weaving is needed
					openAccessTasks.put(member, task);
					return true;
				} else {
					//Yes, so weaving is not needed
					return false;
				}
			}
		}
	}

	/**
	 * Handle a new WeavingTask for a callin binding and 
	 * figures out if weaving is needed for this task 
	 * @param task
	 * @return
	 */
	private boolean addBindingWeavingTask(WeavingTask task) {
		Method method = getMethod(task);
		synchronized (method) {
			synchronized (openBindingTasks) {				
				WeavingTask prevTask = completedBindingTasks.get(method);
				// Is there a already completed task for the method?
				if (prevTask == null) {
					// No, so check the open tasks
					prevTask = openBindingTasks.get(method);
				}
				
				// Is there a open task for the member?
				if (prevTask == null) {
					//No, so weaving is needed
					task.setDoAllTransformations(true);
					openBindingTasks.put(method, task);
					return true;
				}
				
				switch (prevTask.getType()) {
				case WEAVE_BINDING:
					return false;
				case WEAVE_BINDING_OF_SUBCLASS:
					// In  this case only the callAllBings was redefined.
					if (task.getType() != WeavingTaskType.WEAVE_BINDING_OF_SUBCLASS) {
						// Do the other transformations, if the new WeavingTask is not the same
						// as already existing
						openBindingTasks.put(method, task);
						return true;
					}
					return false;
				case WEAVE_INHERITED_BINDING:
					return false;
				default:
					throw new RuntimeException("Unknown WeavingTaskType: "
							+ prevTask.getType().name());
				}
			}
		}
	}
	
	public void addWeavingOfSubclassTask(String methodName, String signature, boolean isStatic) {
		int flags = isStatic ? IBinding.STATIC_BASE : 0;
		addBindingWeavingTask(new WeavingTask(WeavingTaskType.WEAVE_BINDING_OF_SUBCLASS, methodName, signature, flags, true, false));
	}

	/**
	 * Merge tasks of two AbstractBoundClasses (this class and a other).
	 * This method is called if a currently loaded has to be merged 
	 * with a anonymous subclass
	 * @param clazz
	 * @return
	 */
	protected boolean mergeTasks(AbstractBoundClass clazz) {
		boolean isNewTask = false;
		Set<Entry<Method, WeavingTask>> otherBindingTasks;
		Set<Entry<Member, WeavingTask>> otherAccessTasks;
		synchronized (clazz.openBindingTasks) {
			otherBindingTasks = clazz.openBindingTasks.entrySet();
			otherAccessTasks = clazz.openAccessTasks.entrySet();
		}
		for (Map.Entry<Method, WeavingTask> entry : otherBindingTasks) {
			isNewTask |= addWeavingTaskLazy(entry.getValue());
		}		
		for (Map.Entry<Member, WeavingTask> entry : otherAccessTasks) {
			isNewTask |= addWeavingTaskLazy(entry.getValue());
		}
		
		return isNewTask;
	}

	private void weaveBindingInStaticMethod(WeavingTask task) {
		prepareForFirstStaticTransformation();
		Method method = getMethod(task);
		int joinpointId = TeamManager
				.getJoinpointId(getMethodIdentifier(method));
		int boundMethodId = method.getGlobalId(this);

		moveCodeToCallOrig(method, boundMethodId, false);
		createDispatchCodeInOrgMethod(method, joinpointId, boundMethodId);
	}

	/**
	 * Do all transformations for a method, that is not implemented
	 * in this class
	 * @param task
	 */
	private void weaveBindingInNotImplementedMethod(WeavingTask task, boolean needToAddMethod) {
		if ((task.getBaseFlags() & IBinding.STATIC_BASE) == 0)
			prepareForFirstTransformation();
		else
			prepareForFirstStaticTransformation();

		Method method = getMethod(task);
		int joinpointId = TeamManager.getJoinpointId(task.getMethodIdentifier(this));
		int boundMethodId = method.getGlobalId(this);
		if (task.doAllTransformations()) {
			createDispatchCodeInCallAllBindings(joinpointId, boundMethodId);
			// TODO(SH): instead of iterating superclasses fetch it from the Binding
			boolean isWeavable = true; // weavable unless we find it to be declared in an unweavable super
			AbstractBoundClass superClass = getSuperclass();
			while (superClass != null) {
				if (superClass.isJavaLangObject()) {
					isWeavable = false;
					break;
				}
				Method superMethod = superClass.getMethod(task);
				if (superMethod.isImplemented()) {
					isWeavable = weavingContext.isWeavable(superClass.getName(), false, false); // explicitly traversing supers
					break;
				}
				superClass = superClass.getSuperclass();
			}
			if (isWeavable)
				createSuperCallInCallOrig(boundMethodId);
			else
				// can't weave into the declaring class, add an override here:
				createCallAllBindingsCallInOrgMethod(method, boundMethodId, needToAddMethod);
		} else {
			createDispatchCodeInCallAllBindings(joinpointId, boundMethodId);
		}
	}

	/** 
	 * While delegating a task from a sub class to the super class,
 	 * ensure that the super version is actually called.
	 */
	private void weaveSuperCallInCallOrig(WeavingTask task) {
		prepareForFirstTransformation();
		Method method = getMethod(task);
		int boundMethodId = method.getGlobalId(this);
		if (task.doAllTransformations()) {
			createSuperCallInCallOrig(boundMethodId);
		}		
	}

	/**
	 * Do all transformations for a method, that is implemented
	 * in this class
	 * @param task
	 */
	private void weaveBindingInImplementedMethod(WeavingTask task) {
		prepareForFirstTransformation();
		Method method = getMethod(task);
		int joinpointId = TeamManager
				.getJoinpointId(getMethodIdentifier(method));
		int boundMethodId = method.getGlobalId(this);
		if (task.doAllTransformations()) {
			moveCodeToCallOrig(method, boundMethodId, task.requiresBaseSuperCall());
			createDispatchCodeInCallAllBindings(joinpointId, boundMethodId);
			createCallAllBindingsCallInOrgMethod(method, boundMethodId, false);
		} else {
			createDispatchCodeInCallAllBindings(joinpointId, joinpointId);
		}
	}

	/**
	 * Do all transformations for a method, that is bound 
	 * but not implemented in a subclass
	 * @param task
	 */
	private void weaveBindingOfSubclass(WeavingTask task) {
		prepareForFirstTransformation();
		Method method = getMethod(task);
		int boundMethodId = method.getGlobalId(this);
		moveCodeToCallOrig(method, boundMethodId, false);
		createCallAllBindingsCallInOrgMethod(method, boundMethodId, false);

	}

	/** replace all "wicked super calls" targeting the given targetMethod. */
	protected abstract void replaceWickedSuperCalls(AbstractBoundClass superclass, Method targetMethod);

	@Override
	public String toString() {
		return this.name+"["+this.id+"]";
	}

	// See AsmBoundClass or AsmWritableBoundClass for documentation
	
	protected abstract void startTransformation();

	protected abstract void endTransformation(Class<?> definedClass) throws IllegalClassFormatException;

	protected abstract void superTransformation(Class<?> definedClass) throws IllegalClassFormatException;

	protected abstract void prepareAsPossibleBaseClass();

	protected abstract void prepareTeamActivation();

	protected abstract void prepareLiftingParticipant();

	protected abstract void createSuperCallInCallOrig(int boundMethodId);

	protected abstract void createCallAllBindingsCallInOrgMethod(
			Method boundMethod, int joinpointId, boolean needToAddMethod);

	protected abstract void createDispatchCodeInCallAllBindings(
			int joinpointId, int boundMethodId);

	protected abstract void moveCodeToCallOrig(Method boundMethod, int boundMethodId, boolean baseSuperRequired);

	protected abstract void prepareForFirstTransformation();

	protected abstract void prepareForFirstStaticTransformation();

	public abstract boolean isFirstTransformation();

	/** During HCR we need to start with a fresh set of bytes and re-perform all transformations. */
	public abstract void restartTransformation();

	public boolean isLoaded() { return isLoaded; }

	protected abstract void createDispatchCodeInOrgMethod(Method boundMethod,
			int joinpointId, int boundMethodId);

	protected abstract void prepareForFirstMemberAccess();

	protected abstract void weaveFieldAccess(Field field, int accessId);

	protected abstract void weaveMethodAccess(Method method, int accessId);

	public abstract boolean isTransformationActive();
	
	public abstract byte[] getBytecode();

	public void dump(byte[] classfileBuffer, String postfix) {}

	public Collection<@NonNull String> getBoundBaseClasses() { return null; }

	public abstract int compare(String callinLabel1, String callinLabel2);

	public void addWiringTask(ISubclassWiringTask wiringTask) {
		if (this.wiringTasks == null)
			this.wiringTasks = new ArrayList<ISubclassWiringTask>();
		this.wiringTasks.add(wiringTask);
	}

	public void performWiringTasks(AbstractBoundClass superclass, AbstractBoundClass subclass) {
		if (this.wiringTasks == null)
			return;
		synchronized (this.wiringTasks) {			
			for (ISubclassWiringTask task : this.wiringTasks)
				task.wire(superclass, subclass);
			this.wiringTasks.clear();
		}
	}

	public boolean needsWeaving() {
		synchronized (this.openBindingTasks) {			
			return !this.openAccessTasks.isEmpty() || !this.openBindingTasks.isEmpty();
		}
	}

	public void markAsUnweavable() {
		this.isUnweavable = true;
	}

	public abstract void toDebugString(StringBuilder buf, String indent);
}
