/* *******************************************************************
 * Copyright (c) 2002-2010 Contributors
 * 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 
 * ******************************************************************/
package org.aspectj.weaver;

import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.aspectj.bridge.ISourceLocation;

/**
 * Represent a resolved member. Components of it are expected to exist. This member will correspond to a real member *unless* it is
 * being used to represent the effect of an ITD.
 * 
 * @author PARC
 * @author Andy Clement
 */
public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, ResolvedMember {

	private String[] parameterNames = null;
	private boolean isResolved = false;
	protected UnresolvedType[] checkedExceptions = UnresolvedType.NONE;

	/**
	 * if this member is a parameterized version of a member in a generic type, then this field holds a reference to the member we
	 * parameterize.
	 */
	protected ResolvedMember backingGenericMember = null;

	protected AnnotationAJ[] annotations = null;
	protected ResolvedType[] annotationTypes = null;
	protected AnnotationAJ[][] parameterAnnotations = null;
	protected ResolvedType[][] parameterAnnotationTypes = null;

	// Some members are 'created' to represent other things (for example ITDs).
	// These members have their annotations stored elsewhere, and this flag indicates
	// that is the case. It is up to the caller to work out where that is!
	// Once determined the caller may choose to stash the annotations in this
	// member...
	private boolean isAnnotatedElsewhere = false;
	private boolean isAjSynthetic = false;

	// generic methods have type variables
	protected TypeVariable[] typeVariables;

	// these three fields hold the source location of this member
	protected int start, end;
	protected ISourceContext sourceContext = null;

	// XXX deprecate this in favor of the constructor below
	public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, UnresolvedType returnType, String name,
			UnresolvedType[] parameterTypes) {
		super(kind, declaringType, modifiers, returnType, name, parameterTypes);
	}

	public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, UnresolvedType returnType, String name,
			UnresolvedType[] parameterTypes, UnresolvedType[] checkedExceptions) {
		super(kind, declaringType, modifiers, returnType, name, parameterTypes);
		this.checkedExceptions = checkedExceptions;
	}

	public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, UnresolvedType returnType, String name,
			UnresolvedType[] parameterTypes, UnresolvedType[] checkedExceptions, ResolvedMember backingGenericMember) {
		this(kind, declaringType, modifiers, returnType, name, parameterTypes, checkedExceptions);
		this.backingGenericMember = backingGenericMember;
		this.isAjSynthetic = backingGenericMember.isAjSynthetic();
	}

	public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, String name, String signature) {
		super(kind, declaringType, modifiers, name, signature);
	}

	/**
	 * Compute the full set of signatures for a member. This walks up the hierarchy giving the ResolvedMember in each defining type
	 * in the hierarchy. A shadowMember can be created with a target type (declaring type) that does not actually define the member.
	 * This is ok as long as the member is inherited in the declaring type. Each declaring type in the line to the actual declaring
	 * type is added as an additional signature. For example:
	 * 
	 * class A { void foo(); } class B extends A {}
	 * 
	 * shadowMember : void B.foo()
	 * 
	 * gives { void B.foo(), void A.foo() }
	 * 
	 * @param joinPointSignature
	 * @param inAWorld
	 */
	public static JoinPointSignature[] getJoinPointSignatures(Member joinPointSignature, World inAWorld) {

		// Walk up hierarchy creating one member for each type up to and
		// including the
		// first defining type
		ResolvedType originalDeclaringType = joinPointSignature.getDeclaringType().resolve(inAWorld);
		ResolvedMemberImpl firstDefiningMember = (ResolvedMemberImpl) joinPointSignature.resolve(inAWorld);
		if (firstDefiningMember == null) {
			return JoinPointSignature.EMPTY_ARRAY;
		}
		// declaringType can be unresolved if we matched a synthetic member
		// generated by Aj...
		// should be fixed elsewhere but add this resolve call on the end for
		// now so that we can
		// focus on one problem at a time...
		ResolvedType firstDefiningType = firstDefiningMember.getDeclaringType().resolve(inAWorld);
		if (firstDefiningType != originalDeclaringType) {
			if (joinPointSignature.getKind() == Member.CONSTRUCTOR) {
				return JoinPointSignature.EMPTY_ARRAY;
			}
			// else if (shadowMember.isStatic()) {
			// return new ResolvedMember[] {firstDefiningMember};
			// }
		}

		List<ResolvedType> declaringTypes = new ArrayList<ResolvedType>();
		accumulateTypesInBetween(originalDeclaringType, firstDefiningType, declaringTypes);
		Set<ResolvedMember> memberSignatures = new LinkedHashSet<ResolvedMember>();
		for (ResolvedType declaringType : declaringTypes) {
			memberSignatures.add(new JoinPointSignature(firstDefiningMember, declaringType));
		}

		if (shouldWalkUpHierarchyFor(firstDefiningMember)) {
			// now walk up the hierarchy from the firstDefiningMember and
			// include the signature for
			// every type between the firstDefiningMember and the root defining
			// member.
			Iterator<ResolvedType> superTypeIterator = firstDefiningType.getDirectSupertypes();
			List<ResolvedType> typesAlreadyVisited = new ArrayList<ResolvedType>();
			accumulateMembersMatching(firstDefiningMember, superTypeIterator, typesAlreadyVisited, memberSignatures, false);
		}

		JoinPointSignature[] ret = new JoinPointSignature[memberSignatures.size()];
		memberSignatures.toArray(ret);
		return ret;
	}

	private static boolean shouldWalkUpHierarchyFor(Member aMember) {
		if (aMember.getKind() == Member.CONSTRUCTOR) {
			return false;
		}
		if (aMember.getKind() == Member.FIELD) {
			return false;
		}
		if (Modifier.isStatic(aMember.getModifiers())) {
			return false;
		}
		return true;
	}

	/**
	 * Build a list containing every type between subtype and supertype, inclusively.
	 */
	private static void accumulateTypesInBetween(ResolvedType subType, ResolvedType superType, List<ResolvedType> types) {
		types.add(subType);
		if (subType == superType) {
			return;
		} else {
			for (Iterator<ResolvedType> iter = subType.getDirectSupertypes(); iter.hasNext();) {
				ResolvedType parent = iter.next();
				if (superType.isAssignableFrom(parent)) {
					accumulateTypesInBetween(parent, superType, types);
				}
			}
		}
	}

	/**
	 * We have a resolved member, possibly with type parameter references as parameters or return type. We need to find all its
	 * ancestor members. When doing this, a type parameter matches regardless of bounds (bounds can be narrowed down the hierarchy).
	 */
	private static void accumulateMembersMatching(ResolvedMemberImpl memberToMatch, Iterator<ResolvedType> typesToLookIn,
			List<ResolvedType> typesAlreadyVisited, Set<ResolvedMember> foundMembers, boolean ignoreGenerics) {
		while (typesToLookIn.hasNext()) {
			ResolvedType toLookIn = typesToLookIn.next();
			if (!typesAlreadyVisited.contains(toLookIn)) {
				typesAlreadyVisited.add(toLookIn);
				ResolvedMemberImpl foundMember = (ResolvedMemberImpl) toLookIn.lookupResolvedMember(memberToMatch, true,
						ignoreGenerics);
				if (foundMember != null && isVisibleTo(memberToMatch, foundMember)) {
					List<ResolvedType> declaringTypes = new ArrayList<ResolvedType>();
					// declaring type can be unresolved if the member can from
					// an ITD...
					ResolvedType resolvedDeclaringType = foundMember.getDeclaringType().resolve(toLookIn.getWorld());
					accumulateTypesInBetween(toLookIn, resolvedDeclaringType, declaringTypes);
					for (ResolvedType declaringType : declaringTypes) {
						// typesAlreadyVisited.add(declaringType);
						foundMembers.add(new JoinPointSignature(foundMember, declaringType));
					}
					if (!ignoreGenerics && toLookIn.isParameterizedType() && (foundMember.backingGenericMember != null)) {
						foundMembers.add(new JoinPointSignature(foundMember.backingGenericMember, foundMember.declaringType
								.resolve(toLookIn.getWorld())));
					}
					accumulateMembersMatching(foundMember, toLookIn.getDirectSupertypes(), typesAlreadyVisited, foundMembers,
							ignoreGenerics);
					// if this was a parameterized type, look in the generic
					// type that backs it too
				}
			}
		}
	}

	/**
	 * Returns true if the parent member is visible to the child member In the same declaring type this is always true, otherwise if
	 * parent is private it is false.
	 * 
	 * @param childMember
	 * @param parentMember
	 * @return
	 */
	private static boolean isVisibleTo(ResolvedMember childMember, ResolvedMember parentMember) {
		if (childMember.getDeclaringType().equals(parentMember.getDeclaringType())) {
			return true;
		}
		if (Modifier.isPrivate(parentMember.getModifiers())) {
			return false;
		} else {
			return true;
		}
	}

	// ----

	@Override
	public final int getModifiers(World world) {
		return modifiers;
	}

	@Override
	public final int getModifiers() {
		return modifiers;
	}

	// ----

	@Override
	public final UnresolvedType[] getExceptions(World world) {
		return getExceptions();
	}

	public UnresolvedType[] getExceptions() {
		return checkedExceptions;
	}

	public ShadowMunger getAssociatedShadowMunger() {
		return null;
	}

	// ??? true or false?
	public boolean isAjSynthetic() {
		return isAjSynthetic;
	}

	protected void setAjSynthetic(boolean b) {
		isAjSynthetic = b;
	}

	public boolean hasAnnotations() {
		return (annotationTypes != null);
	}

	/**
	 * Check if this member has an annotation of the specified type. If the member has a backing generic member then this member
	 * represents a parameterization of a member in a generic type and the annotations available on the backing generic member
	 * should be used.
	 * 
	 * @param ofType the type of the annotation being searched for
	 * @return true if the annotation is found on this member or its backing generic member
	 */
	public boolean hasAnnotation(UnresolvedType ofType) {
		// The ctors don't allow annotations to be specified ... yet - but
		// that doesn't mean it is an error to call this method.
		// Normally the weaver will be working with subtypes of
		// this type - BcelField/BcelMethod
		if (backingGenericMember != null) {
			if (annotationTypes != null) {
				throw new BCException("Unexpectedly found a backing generic member and a local set of annotations");
			}
			return backingGenericMember.hasAnnotation(ofType);
		}
		if (annotationTypes != null) {
			for (int i = 0, max = annotationTypes.length; i < max; i++) {
				if (annotationTypes[i].equals(ofType)) {
					return true;
				}
			}
		}
		return false;
	}

	public ResolvedType[] getAnnotationTypes() {
		// The ctors don't allow annotations to be specified ... yet - but
		// that doesn't mean it is an error to call this method.
		// Normally the weaver will be working with subtypes of
		// this type - BcelField/BcelMethod
		if (backingGenericMember != null) {
			if (annotationTypes != null) {
				throw new BCException("Unexpectedly found a backing generic member and a local set of annotations");
			}
			return backingGenericMember.getAnnotationTypes();
		}
		return annotationTypes;
	}

	public String getAnnotationDefaultValue() {
		throw new UnsupportedOperationException(
				"You should resolve this member and call getAnnotationDefaultValue() on the result...");
	}

	@Override
	public AnnotationAJ[] getAnnotations() {
		if (backingGenericMember != null) {
			return backingGenericMember.getAnnotations();
		}
		if (annotations!=null) {
			return annotations;
		}
		return super.getAnnotations();
	}

	public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) {
		if (annotations!=null) {
			// this means they have been set (we are likely a placeholder for an ITD, so a fake member)
			for (AnnotationAJ annotation: annotations) {
				if (annotation.getType().equals(ofType)) {
					return annotation;
				}
			}
			return null;
		}
		throw new UnsupportedOperationException("You should resolve this member and call getAnnotationOfType() on the result...");
	}
	
	public void setAnnotations(AnnotationAJ[] annotations) {
		this.annotations = annotations;
	}

	public void setAnnotationTypes(ResolvedType[] annotationTypes) {
		this.annotationTypes = annotationTypes;
	}

	public ResolvedType[][] getParameterAnnotationTypes() {
		return parameterAnnotationTypes;
	}

	public AnnotationAJ[][] getParameterAnnotations() {
		if (backingGenericMember != null) {
			return backingGenericMember.getParameterAnnotations();
		}
		throw new BCException("Cannot return parameter annotations for a " + this.getClass().getName() + " member");
		// return super.getParameterAnnotations();
	}

	public void addAnnotation(AnnotationAJ annotation) {
		if (annotationTypes == null) {
			annotationTypes = new ResolvedType[1];
			annotationTypes[0] = annotation.getType();
			annotations = new AnnotationAJ[1];
			annotations[0] = annotation;
		} else {
			int len = annotations.length;
			AnnotationAJ[] ret = new AnnotationAJ[len + 1];
			System.arraycopy(annotations, 0, ret, 0, len);
			ret[len] = annotation;
			annotations = ret;

			ResolvedType[] newAnnotationTypes = new ResolvedType[len + 1];
			System.arraycopy(annotationTypes, 0, newAnnotationTypes, 0, len);
			newAnnotationTypes[len] = annotation.getType();
			annotationTypes = newAnnotationTypes;
		}
	}

	public boolean isBridgeMethod() {
		return (modifiers & Constants.ACC_BRIDGE) != 0 && getKind().equals(METHOD);
	}

	public boolean isVarargsMethod() {
		return (modifiers & Constants.ACC_VARARGS) != 0;
	}

	public void setVarargsMethod() {
		modifiers = modifiers | Constants.ACC_VARARGS;
	}

	public boolean isSynthetic() {
		// See Bcelmethod.isSynthetic() which takes account of preJava5
		// Synthetic modifier
		return (modifiers & 4096) != 0; // do we know better?
	}

	public void write(CompressingDataOutputStream s) throws IOException {
		getKind().write(s);
		s.writeBoolean(s.canCompress()); // boolean indicates if parts of this are compressed references

		// write out the signature of the declaring type of this member
		if (s.canCompress()) {
			s.writeCompressedSignature(getDeclaringType().getSignature());
		} else {
			getDeclaringType().write(s);
		}

		// write out the modifiers
		s.writeInt(modifiers);

		// write out the name and the signature of this member
		if (s.canCompress()) {
			s.writeCompressedName(getName());
			s.writeCompressedSignature(getSignature());
		} else {
			s.writeUTF(getName());
			s.writeUTF(getSignature());
		}

		// write out the array clauses
		UnresolvedType.writeArray(getExceptions(), s);

		s.writeInt(getStart());
		s.writeInt(getEnd());
		s.writeBoolean(isVarargsMethod());

		// Write out any type variables...
		if (typeVariables == null) {
			s.writeByte(0);
		} else {
			s.writeByte(typeVariables.length);
			for (int i = 0; i < typeVariables.length; i++) {
				typeVariables[i].write(s);
			}
		}
		String gsig = getGenericSignature();

		// change this to a byte: 255=false 0>254 means true and encodes the number of parameters
		if (getSignature().equals(gsig)) {
			s.writeByte(0xff);
		} else {
			s.writeByte(parameterTypes.length);
			for (int i = 0; i < parameterTypes.length; i++) {
				if (s.canCompress()) {
					s.writeCompressedSignature(parameterTypes[i].getSignature());
				} else {
					UnresolvedType array_element = parameterTypes[i];
					array_element.write(s);
				}
			}
			if (s.canCompress()) {
				s.writeCompressedSignature(returnType.getSignature());
			} else {
				returnType.write(s);
			}
		}
	}

	/**
	 * Return the member generic signature that would be suitable for inclusion in a class file Signature attribute. For: <T>
	 * List<String> getThem(T t) {} we would create: <T:Ljava/lang/Object;>(TT;)Ljava/util/List<Ljava/lang/String;>;;
	 * 
	 * @return the generic signature for the member that could be inserted into a class file
	 */
	public String getSignatureForAttribute() {
		StringBuffer sb = new StringBuffer();
		if (typeVariables != null) {
			sb.append("<");
			for (int i = 0; i < typeVariables.length; i++) {
				sb.append(typeVariables[i].getSignatureForAttribute()); // need
				// a
				// 'getSignatureForAttribute()'
			}
			sb.append(">");
		}
		sb.append("(");
		for (int i = 0; i < parameterTypes.length; i++) {
			ResolvedType ptype = (ResolvedType) parameterTypes[i];
			sb.append(ptype.getSignatureForAttribute());
		}
		sb.append(")");
		sb.append(((ResolvedType) returnType).getSignatureForAttribute());
		return sb.toString();
	}

	public String getGenericSignature() {
		StringBuffer sb = new StringBuffer();
		if (typeVariables != null) {
			sb.append("<");
			for (int i = 0; i < typeVariables.length; i++) {
				sb.append(typeVariables[i].getSignature());
			}
			sb.append(">");
		}
		sb.append("(");
		for (int i = 0; i < parameterTypes.length; i++) {
			UnresolvedType ptype = parameterTypes[i];
			sb.append(ptype.getSignature());
		}
		sb.append(")");
		sb.append(returnType.getSignature());
		return sb.toString();
	}

	public static void writeArray(ResolvedMember[] members, CompressingDataOutputStream s) throws IOException {
		s.writeInt(members.length);
		for (int i = 0, len = members.length; i < len; i++) {
			members[i].write(s);
		}
	}

	public static ResolvedMemberImpl readResolvedMember(VersionedDataInputStream s, ISourceContext sourceContext)
			throws IOException {

		MemberKind mk = MemberKind.read(s);
		boolean compressed = (s.isAtLeast169() ? s.readBoolean() : false);
		UnresolvedType declaringType = compressed ? UnresolvedType.forSignature(s.readUtf8(s.readShort())) : UnresolvedType.read(s);
		int modifiers = s.readInt();
		String name = compressed ? s.readUtf8(s.readShort()) : s.readUTF();
		String signature = compressed ? s.readUtf8(s.readShort()) : s.readUTF();
		ResolvedMemberImpl m = new ResolvedMemberImpl(mk, declaringType, modifiers, name, signature);
		m.checkedExceptions = UnresolvedType.readArray(s);

		m.start = s.readInt();
		m.end = s.readInt();
		m.sourceContext = sourceContext;

		if (s.getMajorVersion() >= AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {

			if (s.getMajorVersion() >= AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150M4) {
				boolean isvarargs = s.readBoolean();
				if (isvarargs) {
					m.setVarargsMethod();
				}
			}

			int tvcount = s.isAtLeast169() ? s.readByte() : s.readInt();
			if (tvcount != 0) {
				m.typeVariables = new TypeVariable[tvcount];
				for (int i = 0; i < tvcount; i++) {
					m.typeVariables[i] = TypeVariable.read(s);
					m.typeVariables[i].setDeclaringElement(m);
					m.typeVariables[i].setRank(i);
				}
			}
			if (s.getMajorVersion() >= AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150M4) {
				int pcount = -1;
				boolean hasAGenericSignature = false;
				if (s.isAtLeast169()) {
					pcount = s.readByte();
					hasAGenericSignature = (pcount >= 0 && pcount < 255);
				} else {
					hasAGenericSignature = s.readBoolean();
				}
				if (hasAGenericSignature) {
					int ps = (s.isAtLeast169() ? pcount : s.readInt());
					UnresolvedType[] params = new UnresolvedType[ps];
					for (int i = 0; i < params.length; i++) {
						if (compressed) {
							params[i] = TypeFactory.createTypeFromSignature(s.readSignature());
						} else {
							params[i] = TypeFactory.createTypeFromSignature(s.readUTF());
						}
					}
					UnresolvedType rt = compressed ? TypeFactory.createTypeFromSignature(s.readSignature()) : TypeFactory
							.createTypeFromSignature(s.readUTF());
					m.parameterTypes = params;
					m.returnType = rt;
				}
			}
		}
		return m;
	}

	public static ResolvedMember[] readResolvedMemberArray(VersionedDataInputStream s, ISourceContext context) throws IOException {
		int len = s.readInt();
		ResolvedMember[] members = new ResolvedMember[len];
		for (int i = 0; i < len; i++) {
			members[i] = ResolvedMemberImpl.readResolvedMember(s, context);
		}
		return members;
	}

	// OPTIMIZE dont like how resolve(world) on ResolvedMemberImpl does
	// something different to world.resolve(member)
	@Override
	public ResolvedMember resolve(World world) {
		if (isResolved) {
			return this;
		}
		// make sure all the pieces of a resolvedmember really are resolved
		try {
			if (typeVariables != null && typeVariables.length > 0) {
				for (int i = 0; i < typeVariables.length; i++) {
					typeVariables[i] = typeVariables[i].resolve(world);
				}
			}
			world.setTypeVariableLookupScope(this);
			// if (annotationTypes != null) {
			// Set<ResolvedType> r = new HashSet<ResolvedType>();
			// for (UnresolvedType element : annotationTypes) {
			// // for (Iterator iter = annotationTypes.iterator(); iter.hasNext();) {
			// // UnresolvedType element = (UnresolvedType) iter.next();
			// r.add(world.resolve(element));
			// }
			// annotationTypes = r;
			// }
			declaringType = declaringType.resolve(world);
			if (declaringType.isRawType()) {
				declaringType = ((ReferenceType) declaringType).getGenericType();
			}

			if (parameterTypes != null && parameterTypes.length > 0) {
				for (int i = 0; i < parameterTypes.length; i++) {
					parameterTypes[i] = parameterTypes[i].resolve(world);
				}
			}

			returnType = returnType.resolve(world);

		} finally {
			world.setTypeVariableLookupScope(null);
		}
		isResolved = true;
		return this;
	}

	public ISourceContext getSourceContext(World world) {
		return getDeclaringType().resolve(world).getSourceContext();
	}

	public String[] getParameterNames() {
		return parameterNames;
	}

	public final void setParameterNames(String[] pnames) {
		parameterNames = pnames;
	}

	@Override
	public final String[] getParameterNames(World world) {
		return getParameterNames();
	}

	public AjAttribute.EffectiveSignatureAttribute getEffectiveSignature() {
		return null;
	}

	public ISourceLocation getSourceLocation() {
		// System.out.println("get context: " + this + " is " + sourceContext);
		if (getSourceContext() == null) {
			// System.err.println("no context: " + this);
			return null;
		}
		return getSourceContext().makeSourceLocation(this);
	}

	public int getEnd() {
		return end;
	}

	public ISourceContext getSourceContext() {
		return sourceContext;
	}

	public int getStart() {
		return start;
	}

	public void setPosition(int sourceStart, int sourceEnd) {
		this.start = sourceStart;
		this.end = sourceEnd;
	}

	public void setDeclaringType(ReferenceType rt) {
		declaringType = rt;
	}

	public void setSourceContext(ISourceContext sourceContext) {
		this.sourceContext = sourceContext;
	}

	public boolean isAbstract() {
		return Modifier.isAbstract(modifiers);
	}

	public boolean isPublic() {
		return Modifier.isPublic(modifiers);
	}

	public boolean isDefault() {
		int mods = getModifiers();
		return !(Modifier.isPublic(mods) || Modifier.isProtected(mods) || Modifier.isPrivate(mods));
	}

	public boolean isVisible(ResolvedType fromType) {
		UnresolvedType declaringType = getDeclaringType();
		ResolvedType type = null;
		if (fromType.equals(declaringType)) {
			type = fromType;
		} else {
			World world = fromType.getWorld();
			type = declaringType.resolve(world);
		}
		return ResolvedType.isVisible(getModifiers(), type, fromType);
	}

	public void setCheckedExceptions(UnresolvedType[] checkedExceptions) {
		this.checkedExceptions = checkedExceptions;
	}

	public void setAnnotatedElsewhere(boolean b) {
		isAnnotatedElsewhere = b;
	}

	public boolean isAnnotatedElsewhere() {
		return isAnnotatedElsewhere;
	}

	/**
	 * Get the UnresolvedType for the return type, taking generic signature into account
	 */
	@Override
	public UnresolvedType getGenericReturnType() {
		return getReturnType();
	}

	/**
	 * Get the TypeXs of the parameter types, taking generic signature into account
	 */
	@Override
	public UnresolvedType[] getGenericParameterTypes() {
		return getParameterTypes();
	}

	public ResolvedMemberImpl parameterizedWith(UnresolvedType[] typeParameters, ResolvedType newDeclaringType,
			boolean isParameterized) {
		return parameterizedWith(typeParameters, newDeclaringType, isParameterized, null);
	}

	/**
	 * Return a resolvedmember in which all the type variables in the signature have been replaced with the given bindings. The
	 * 'isParameterized' flag tells us whether we are creating a raw type version or not. if (isParameterized) then List<T> will
	 * turn into List<String> (for example) - if (!isParameterized) then List<T> will turn into List.
	 */
	public ResolvedMemberImpl parameterizedWith(UnresolvedType[] typeParameters, ResolvedType newDeclaringType,
			boolean isParameterized, List<String> aliases) {
		// PR308773
		// this check had problems for the inner type of a generic type because the inner type can be represented
		// by a 'simple type' if it is only sharing type variables with the outer and has none of its own. To avoid the
		// check going bang in this case we check for $ (crap...) - we can't check the outer because the declaring type
		// is considered unresolved...
		if (// isParameterized && <-- might need this bit...
		!getDeclaringType().isGenericType() && getDeclaringType().getName().indexOf("$") == -1) {
			throw new IllegalStateException("Can't ask to parameterize a member of non-generic type: " + getDeclaringType()
					+ "  kind(" + getDeclaringType().typeKind + ")");
		}
		TypeVariable[] typeVariables = getDeclaringType().getTypeVariables();
		if (isParameterized && (typeVariables.length != typeParameters.length)) {
			throw new IllegalStateException("Wrong number of type parameters supplied");
		}
		Map<String, UnresolvedType> typeMap = new HashMap<String, UnresolvedType>();
		boolean typeParametersSupplied = typeParameters != null && typeParameters.length > 0;
		if (typeVariables != null) {
			// If no 'replacements' were supplied in the typeParameters array
			// then collapse
			// type variables to their first bound.
			for (int i = 0; i < typeVariables.length; i++) {
				UnresolvedType ut = (!typeParametersSupplied ? typeVariables[i].getFirstBound() : typeParameters[i]);
				typeMap.put(typeVariables[i].getName(), ut);
			}
		}
		// For ITDs on generic types that use type variables from the target type, the aliases
		// record the alternative names used throughout the ITD expression that must map to
		// the same value as the type variables real name.
		if (aliases != null) {
			int posn = 0;
			for (String typeVariableAlias : aliases) {
				typeMap.put(typeVariableAlias, (!typeParametersSupplied ? typeVariables[posn].getFirstBound()
						: typeParameters[posn]));
				posn++;
			}
		}

		UnresolvedType parameterizedReturnType = parameterize(getGenericReturnType(), typeMap, isParameterized,
				newDeclaringType.getWorld());
		UnresolvedType[] parameterizedParameterTypes = new UnresolvedType[getGenericParameterTypes().length];
		UnresolvedType[] genericParameterTypes = getGenericParameterTypes();
		for (int i = 0; i < parameterizedParameterTypes.length; i++) {
			parameterizedParameterTypes[i] = parameterize(genericParameterTypes[i], typeMap, isParameterized,
					newDeclaringType.getWorld());
		}
		ResolvedMemberImpl ret = new ResolvedMemberImpl(getKind(), newDeclaringType, getModifiers(), parameterizedReturnType,
				getName(), parameterizedParameterTypes, getExceptions(), this);
		ret.setTypeVariables(getTypeVariables());
		ret.setSourceContext(getSourceContext());
		ret.setPosition(getStart(), getEnd());
		ret.setParameterNames(getParameterNames());
		return ret;
	}

	/**
	 * Replace occurrences of type variables in the signature with values contained in the map. The map is of the form
	 * A=String,B=Integer and so a signature List<A> Foo.m(B i) {} would become List<String> Foo.m(Integer i) {}
	 */
	public ResolvedMember parameterizedWith(Map<String, UnresolvedType> m, World w) {
		// if (//isParameterized && <-- might need this bit...
		// !getDeclaringType().isGenericType()) {
		// throw new IllegalStateException(
		// "Can't ask to parameterize a member of non-generic type: "
		// +getDeclaringType()+"  kind("+
		// getDeclaringType().typeKind+")");
		// }
		declaringType = declaringType.resolve(w);
		if (declaringType.isRawType()) {
			declaringType = ((ResolvedType) declaringType).getGenericType();
			// TypeVariable[] typeVariables = getDeclaringType().getTypeVariables();
			// if (isParameterized && (typeVariables.length !=
			// typeParameters.length)) {
			// throw new
			// IllegalStateException("Wrong number of type parameters supplied");
			// }
			// Map typeMap = new HashMap();
			// boolean typeParametersSupplied = typeParameters!=null &&
			// typeParameters.length>0;
			// if (typeVariables!=null) {
			// // If no 'replacements' were supplied in the typeParameters array
			// then collapse
			// // type variables to their first bound.
			// for (int i = 0; i < typeVariables.length; i++) {
			// UnresolvedType ut =
			// (!typeParametersSupplied?typeVariables[i].getFirstBound
			// ():typeParameters[i]);
			// typeMap.put(typeVariables[i].getName(),ut);
			// }
			// }
			// // For ITDs on generic types that use type variables from the target
			// type, the aliases
			// // record the alternative names used throughout the ITD expression
			// that must map to
			// // the same value as the type variables real name.
			// if (aliases!=null) {
			// int posn = 0;
			// for (Iterator iter = aliases.iterator(); iter.hasNext();) {
			// String typeVariableAlias = (String) iter.next();
			// typeMap.put(typeVariableAlias,(!typeParametersSupplied?typeVariables[
			// posn].getFirstBound():typeParameters[posn]));
			// posn++;
			// }
			// }
		}

		UnresolvedType parameterizedReturnType = parameterize(getGenericReturnType(), m, true, w);
		UnresolvedType[] parameterizedParameterTypes = new UnresolvedType[getGenericParameterTypes().length];
		UnresolvedType[] genericParameterTypes = getGenericParameterTypes();
		for (int i = 0; i < parameterizedParameterTypes.length; i++) {
			parameterizedParameterTypes[i] = parameterize(genericParameterTypes[i], m, true, w);
		}
		ResolvedMemberImpl ret = new ResolvedMemberImpl(getKind(), declaringType, getModifiers(), parameterizedReturnType,
				getName(), parameterizedParameterTypes, getExceptions(), this);
		ret.setTypeVariables(getTypeVariables());
		ret.setSourceContext(getSourceContext());
		ret.setPosition(getStart(), getEnd());
		ret.setParameterNames(getParameterNames());
		return ret;
	}

	public void setTypeVariables(TypeVariable[] tvars) {
		typeVariables = tvars;
	}

	public TypeVariable[] getTypeVariables() {
		return typeVariables;
	}

	protected UnresolvedType parameterize(UnresolvedType aType, Map<String, UnresolvedType> typeVariableMap,
			boolean inParameterizedType, World w) {
		if (aType instanceof TypeVariableReference) {
			String variableName = ((TypeVariableReference) aType).getTypeVariable().getName();
			if (!typeVariableMap.containsKey(variableName)) {
				return aType; // if the type variable comes from the method (and
				// not the type) thats OK
			}
			return typeVariableMap.get(variableName);
		} else if (aType.isParameterizedType()) {
			if (inParameterizedType) {
				if (w != null) {
					aType = aType.resolve(w);
				} else {
					UnresolvedType dType = getDeclaringType();
					aType = aType.resolve(((ResolvedType) dType).getWorld());
				}
				return aType.parameterize(typeVariableMap);
			} else {
				return aType.getRawType();
			}
		} else if (aType.isArray()) {
			// The component type might be a type variable (pr150095)
			int dims = 1;
			String sig = aType.getSignature();
			// while (sig.charAt(dims) == '[')
			// dims++;
			UnresolvedType arrayType = null;
			UnresolvedType componentSig = UnresolvedType.forSignature(sig.substring(dims));
			UnresolvedType parameterizedComponentSig = parameterize(componentSig, typeVariableMap, inParameterizedType, w);
			if (parameterizedComponentSig.isTypeVariableReference()
					&& parameterizedComponentSig instanceof UnresolvedTypeVariableReferenceType
					&& typeVariableMap.containsKey(((UnresolvedTypeVariableReferenceType) parameterizedComponentSig)
							.getTypeVariable().getName())) { // pr250632
				// TODO ASC bah, this code is rubbish - i should fix it properly
				StringBuffer newsig = new StringBuffer();
				newsig.append("[T");
				newsig.append(((UnresolvedTypeVariableReferenceType) parameterizedComponentSig).getTypeVariable().getName());
				newsig.append(";");
				arrayType = UnresolvedType.forSignature(newsig.toString());
			} else {
				arrayType = ResolvedType.makeArray(parameterizedComponentSig, dims);
			}
			return arrayType;
		}
		return aType;
	}

	/**
	 * If this member is defined by a parameterized super-type, return the erasure of that member. For example: interface I<T> { T
	 * foo(T aTea); } class C implements I<String> { String foo(String aString) { return "something"; } } The resolved member for
	 * C.foo has signature String foo(String). The erasure of that member is Object foo(Object) -- use upper bound of type variable.
	 * A type is a supertype of itself.
	 */
	// public ResolvedMember getErasure() {
	// if (calculatedMyErasure) return myErasure;
	// calculatedMyErasure = true;
	// ResolvedType resolvedDeclaringType = (ResolvedType) getDeclaringType();
	// // this next test is fast, and the result is cached.
	// if (!resolvedDeclaringType.hasParameterizedSuperType()) {
	// return null;
	// } else {
	// // we have one or more parameterized super types.
	// // this member may be defined by one of them... we need to find out.
	// Collection declaringTypes =
	// this.getDeclaringTypes(resolvedDeclaringType.getWorld());
	// for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) {
	// ResolvedType aDeclaringType = (ResolvedType) iter.next();
	// if (aDeclaringType.isParameterizedType()) {
	// // we've found the (a?) parameterized type that defines this member.
	// // now get the erasure of it
	// ResolvedMemberImpl matchingMember = (ResolvedMemberImpl)
	// aDeclaringType.lookupMemberNoSupers(this);
	// if (matchingMember != null && matchingMember.backingGenericMember !=
	// null) {
	// myErasure = matchingMember.backingGenericMember;
	// return myErasure;
	// }
	// }
	// }
	// }
	// return null;
	// }
	//
	// private ResolvedMember myErasure = null;
	// private boolean calculatedMyErasure = false;
	public boolean hasBackingGenericMember() {
		return backingGenericMember != null;
	}

	public ResolvedMember getBackingGenericMember() {
		return backingGenericMember;
	}

	/**
	 * For ITDs, we use the default factory methods to build a resolved member, then alter a couple of characteristics using this
	 * method - this is safe.
	 */
	public void resetName(String newName) {
		this.name = newName;
	}

	public void resetKind(MemberKind newKind) {
		this.kind = newKind;
	}

	public void resetModifiers(int newModifiers) {
		this.modifiers = newModifiers;
	}

	public void resetReturnTypeToObjectArray() {
		returnType = UnresolvedType.OBJECTARRAY;
	}

	/**
	 * Returns true if this member matches the other. The matching takes into account name and parameter types only. When comparing
	 * parameter types, we allow any type variable to match any other type variable regardless of bounds.
	 */
	public boolean matches(ResolvedMember aCandidateMatch, boolean ignoreGenerics) {
		ResolvedMemberImpl candidateMatchImpl = (ResolvedMemberImpl) aCandidateMatch;
		if (!getName().equals(aCandidateMatch.getName())) {
			return false;
		}
		UnresolvedType[] parameterTypes = getGenericParameterTypes();
		UnresolvedType[] candidateParameterTypes = aCandidateMatch.getGenericParameterTypes();
		if (parameterTypes.length != candidateParameterTypes.length) {
			return false;
		}
		boolean b = false;
		/*
		 * if (ignoreGenerics) { String myParameterSignature = getParameterSigWithBoundsRemoved(); String
		 * candidateParameterSignature = candidateMatchImpl.getParameterSigWithBoundsRemoved(); if
		 * (myParameterSignature.equals(candidateParameterSignature)) { b = true; } else { myParameterSignature =
		 * (hasBackingGenericMember() ? backingGenericMember.getParameterSignatureErased() : getParameterSignatureErased());
		 * candidateParameterSignature = (candidateMatchImpl.hasBackingGenericMember() ? candidateMatchImpl.backingGenericMember
		 * .getParameterSignatureErased() : candidateMatchImpl.getParameterSignatureErased()); // System.out.println("my psig = " +
		 * myParameterSignature); // System.out.println("can psig = " + candidateParameterSignature); b =
		 * myParameterSignature.equals(candidateParameterSignature); } } else {
		 */
		String myParameterSignature = getParameterSigWithBoundsRemoved();
		String candidateParameterSignature = candidateMatchImpl.getParameterSigWithBoundsRemoved();
		if (myParameterSignature.equals(candidateParameterSignature)) {
			b = true;
		} else {
			// try erasure
			myParameterSignature = getParameterSignatureErased();
			candidateParameterSignature = candidateMatchImpl.getParameterSignatureErased();
			// myParameterSignature = (hasBackingGenericMember() ? backingGenericMember.getParameterSignatureErased()
			// : getParameterSignatureErased());
			// candidateParameterSignature = (candidateMatchImpl.hasBackingGenericMember() ?
			// candidateMatchImpl.backingGenericMember
			// .getParameterSignatureErased() : candidateMatchImpl.getParameterSignatureErased());
			// System.out.println("my psig = " + myParameterSignature);
			// System.out.println("can psig = " + candidateParameterSignature);
			b = myParameterSignature.equals(candidateParameterSignature);
			// }
		}
		// System.out.println("Checking param signatures: " + b);
		return b;
	}

	/**
	 * converts e.g. <T extends Number>.... List<T> to just Ljava/util/List<T;>; whereas the full signature would be
	 * Ljava/util/List<T:Ljava/lang/Number;>;
	 */
	private String myParameterSignatureWithBoundsRemoved = null;
	/**
	 * converts e.g. <T extends Number>.... List<T> to just Ljava/util/List;
	 */
	private String myParameterSignatureErasure = null;

	// does NOT produce a meaningful java signature, but does give a unique
	// string suitable for
	// comparison.
	private String getParameterSigWithBoundsRemoved() {
		if (myParameterSignatureWithBoundsRemoved != null) {
			return myParameterSignatureWithBoundsRemoved;
		}
		StringBuffer sig = new StringBuffer();
		UnresolvedType[] myParameterTypes = getGenericParameterTypes();
		for (int i = 0; i < myParameterTypes.length; i++) {
			appendSigWithTypeVarBoundsRemoved(myParameterTypes[i], sig, new HashSet<UnresolvedType>());
		}
		myParameterSignatureWithBoundsRemoved = sig.toString();
		return myParameterSignatureWithBoundsRemoved;
	}

	/**
	 * Return the erased form of the signature with bounds collapsed for type variables, etc. Does not include the return type, @see
	 * getParam
	 */
	public String getParameterSignatureErased() {
		if (myParameterSignatureErasure == null) {
			StringBuilder sig = new StringBuilder();
			for (UnresolvedType parameter : getParameterTypes()) {
				sig.append(parameter.getErasureSignature());
			}
			myParameterSignatureErasure = sig.toString();
		}
		return myParameterSignatureErasure;
	}

	public String getSignatureErased() {
		StringBuffer sb = new StringBuffer();
		sb.append("(");
		sb.append(getParameterSignatureErased());
		sb.append(")");
		sb.append(getReturnType().getErasureSignature());
		return sb.toString();
	}

	// does NOT produce a meaningful java signature, but does give a unique
	// string suitable for
	// comparison.
	public static void appendSigWithTypeVarBoundsRemoved(UnresolvedType aType, StringBuffer toBuffer,
			Set<UnresolvedType> alreadyUsedTypeVars) {
		if (aType.isTypeVariableReference()) {
			TypeVariableReferenceType typeVariableRT = (TypeVariableReferenceType) aType;
			// pr204505
			if (alreadyUsedTypeVars.contains(aType)) {
				toBuffer.append("...");
			} else {
				alreadyUsedTypeVars.add(aType);
				appendSigWithTypeVarBoundsRemoved(typeVariableRT.getTypeVariable().getFirstBound(), toBuffer, alreadyUsedTypeVars);
			}
			// toBuffer.append("T;");
		} else if (aType.isParameterizedType()) {
			toBuffer.append(aType.getRawType().getSignature());
			toBuffer.append("<");
			for (int i = 0; i < aType.getTypeParameters().length; i++) {
				appendSigWithTypeVarBoundsRemoved(aType.getTypeParameters()[i], toBuffer, alreadyUsedTypeVars);
			}
			toBuffer.append(">;");
		} else {
			toBuffer.append(aType.getSignature());
		}
	}

	/**
	 * Useful for writing tests, returns *everything* we know about this member.
	 */
	public String toDebugString() {
		StringBuffer r = new StringBuffer();

		// modifiers
		int mods = modifiers;
		if ((mods & 4096) > 0) {
			mods = mods - 4096; // remove synthetic (added in the ASM case but
		}
		// not in the BCEL case...)
		if ((mods & 512) > 0) {
			mods = mods - 512; // remove interface (added in the BCEL case but
		}
		// not in the ASM case...)
		if ((mods & 131072) > 0) {
			mods = mods - 131072; // remove deprecated (added in the ASM case
		}
		// but not in the BCEL case...)
		String modsStr = Modifier.toString(mods);
		if (modsStr.length() != 0) {
			r.append(modsStr).append("(" + mods + ")").append(" ");
		}

		// type variables
		if (typeVariables != null && typeVariables.length > 0) {
			r.append("<");
			for (int i = 0; i < typeVariables.length; i++) {
				if (i > 0) {
					r.append(",");
				}
				TypeVariable t = typeVariables[i];
				r.append(t.toDebugString());
			}
			r.append("> ");
		}

		// 'declaring' type
		r.append(getGenericReturnType().toDebugString());
		r.append(' ');

		// name
		r.append(declaringType.getName());
		r.append('.');
		r.append(name);

		// parameter signature if a method
		if (kind != FIELD) {
			r.append("(");
			UnresolvedType[] params = getGenericParameterTypes();
			boolean parameterNamesExist = showParameterNames && parameterNames != null && parameterNames.length == params.length;
			if (params.length != 0) {
				for (int i = 0, len = params.length; i < len; i++) {
					if (i > 0) {
						r.append(", ");
					}
					r.append(params[i].toDebugString());
					if (parameterNamesExist) {
						r.append(" ").append(parameterNames[i]);
					}
				}
			}
			r.append(")");
		}
		return r.toString();
	}

	// SECRETAPI - controlling whether parameter names come out in the debug
	// string (for testing purposes)
	public static boolean showParameterNames = true;

	public String toGenericString() {
		StringBuffer buf = new StringBuffer();
		buf.append(getGenericReturnType().getSimpleName());
		buf.append(' ');
		buf.append(declaringType.getName());
		buf.append('.');
		buf.append(name);
		if (kind != FIELD) {
			buf.append("(");
			UnresolvedType[] params = getGenericParameterTypes();
			if (params.length != 0) {
				buf.append(params[0].getSimpleName());
				for (int i = 1, len = params.length; i < len; i++) {
					buf.append(", ");
					buf.append(params[i].getSimpleName());
				}
			}
			buf.append(")");
		}
		return buf.toString();
	}

	public boolean isCompatibleWith(Member am) {
		if (kind != METHOD || am.getKind() != METHOD) {
			return true;
		}
		if (!name.equals(am.getName())) {
			return true;
		}
		if (!equalTypes(getParameterTypes(), am.getParameterTypes())) {
			return true;
		}
		return getReturnType().equals(am.getReturnType());
	}

	private static boolean equalTypes(UnresolvedType[] a, UnresolvedType[] b) {
		int len = a.length;
		if (len != b.length) {
			return false;
		}
		for (int i = 0; i < len; i++) {
			if (!a[i].equals(b[i])) {
				return false;
			}
		}
		return true;
	}

	public TypeVariable getTypeVariableNamed(String name) {
		// Check locally...
		if (typeVariables != null) {
			for (int i = 0; i < typeVariables.length; i++) {
				if (typeVariables[i].getName().equals(name)) {
					return typeVariables[i];
				}
			}
		}
		// check the declaring type!
		return declaringType.getTypeVariableNamed(name);

		// Do generic aspects with ITDs that share type variables with the
		// aspect and the target type and have their own tvars cause
		// this to be messier?
	}

	public void evictWeavingState() {
	}


	public boolean isEquivalentTo(Object other) {
		return this.equals(other);
	}

	public boolean isDefaultConstructor() {
		return false;
	}
}
