/* *******************************************************************
 * 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
 *
 * Contributors:
 *     PARC                 initial implementation
 *     Alexandre Vasseur    support for @AJ perClause
 * ******************************************************************/

package org.aspectj.ajdt.internal.compiler.lookup;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.aspectj.ajdt.internal.compiler.ast.AdviceDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.DeclareAnnotationDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.DeclareDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.InterTypeDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration;
import org.aspectj.ajdt.internal.core.builder.EclipseSourceContext;
import org.aspectj.bridge.IMessage;
import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Literal;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NameReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteral;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.aspectj.weaver.AbstractReferenceTypeDelegate;
import org.aspectj.weaver.AnnotationAJ;
import org.aspectj.weaver.AnnotationAnnotationValue;
import org.aspectj.weaver.AnnotationNameValuePair;
import org.aspectj.weaver.AnnotationTargetKind;
import org.aspectj.weaver.AnnotationValue;
import org.aspectj.weaver.ArrayAnnotationValue;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ClassAnnotationValue;
import org.aspectj.weaver.EnumAnnotationValue;
import org.aspectj.weaver.ReferenceType;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedMemberImpl;
import org.aspectj.weaver.ResolvedPointcutDefinition;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.StandardAnnotation;
import org.aspectj.weaver.TypeVariable;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.WeaverStateInfo;
import org.aspectj.weaver.World;
import org.aspectj.weaver.bcel.AtAjAttributes.LazyResolvedPointcutDefinition;
import org.aspectj.weaver.patterns.Declare;
import org.aspectj.weaver.patterns.FormalBinding;
import org.aspectj.weaver.patterns.ParserException;
import org.aspectj.weaver.patterns.PatternParser;
import org.aspectj.weaver.patterns.PerClause;
import org.aspectj.weaver.patterns.PerFromSuper;
import org.aspectj.weaver.patterns.PerSingleton;
import org.aspectj.weaver.patterns.Pointcut;

/**
 * Supports viewing eclipse TypeDeclarations/SourceTypeBindings as a ResolvedType
 * 
 * @author Jim Hugunin
 * @author Andy Clement
 */
public class EclipseSourceType extends AbstractReferenceTypeDelegate {
	private static final char[] pointcutSig = "Lorg/aspectj/lang/annotation/Pointcut;".toCharArray();
	private static final char[] aspectSig = "Lorg/aspectj/lang/annotation/Aspect;".toCharArray();
	protected ResolvedPointcutDefinition[] declaredPointcuts = null;
	protected ResolvedMember[] declaredMethods = null;
	protected ResolvedMember[] declaredFields = null;

	public List<Declare> declares = new ArrayList<Declare>();
	public List<EclipseTypeMunger> typeMungers = new ArrayList<EclipseTypeMunger>();

	private final EclipseFactory factory;

	private final SourceTypeBinding binding;
	private final TypeDeclaration declaration;
	private final CompilationUnitDeclaration unit;
	private boolean annotationsFullyResolved = false;
	private boolean annotationTypesAreResolved = false;
	private ResolvedType[] annotationTypes = null;

	private boolean discoveredAnnotationTargetKinds = false;
	private AnnotationTargetKind[] annotationTargetKinds;
	private AnnotationAJ[] annotations = null;

	protected EclipseFactory eclipseWorld() {
		return factory;
	}

	public EclipseSourceType(ReferenceType resolvedTypeX, EclipseFactory factory, SourceTypeBinding binding,
			TypeDeclaration declaration, CompilationUnitDeclaration unit) {
		super(resolvedTypeX, true);
		this.factory = factory;
		this.binding = binding;
		this.declaration = declaration;
		this.unit = unit;

		setSourceContext(new EclipseSourceContext(declaration.compilationResult));
		resolvedTypeX.setStartPos(declaration.sourceStart);
		resolvedTypeX.setEndPos(declaration.sourceEnd);
	}

	public boolean isAspect() {
		final boolean isCodeStyle = declaration instanceof AspectDeclaration;
		return isCodeStyle ? isCodeStyle : isAnnotationStyleAspect();
	}

	public boolean isAnonymous() {
		if (declaration.binding != null) {
			return declaration.binding.isAnonymousType();
		}
		return ((declaration.modifiers & (ASTNode.IsAnonymousType | ASTNode.IsLocalType)) != 0);
	}

	public boolean isNested() {
		if (declaration.binding != null) {
			return (declaration.binding.isMemberType());
		}
		return ((declaration.modifiers & ASTNode.IsMemberType) != 0);
	}

	public ResolvedType getOuterClass() {
		if (declaration.binding != null) {
			ReferenceBinding enclosingType = declaration.binding.enclosingType();
			return enclosingType==null?null:eclipseWorld().fromEclipse(enclosingType);
		}
		// TODO are we going to make a mistake here if the binding is null?
		// Do we ever get asked when the binding is null
		if (declaration.enclosingType == null) {
			return null;
		}
		return eclipseWorld().fromEclipse(declaration.enclosingType.binding);
	}

	public boolean isAnnotationStyleAspect() {
		if (declaration.annotations == null) {
			return false;
		}
		ResolvedType[] annotations = getAnnotationTypes();
		for (int i = 0; i < annotations.length; i++) {
			if ("org.aspectj.lang.annotation.Aspect".equals(annotations[i].getName())) {
				return true;
			}
		}
		return false;
	}

	/** Returns "" if there is a problem */
	private String getPointcutStringFromAnnotationStylePointcut(AbstractMethodDeclaration amd) {
		Annotation[] ans = amd.annotations;
		if (ans == null) {
			return "";
		}
		for (int i = 0; i < ans.length; i++) {
			if (ans[i].resolvedType == null) {
				continue; // XXX happens if we do this very early from
			}
			// buildInterTypeandPerClause
			// may prevent us from resolving references made in @Pointcuts to
			// an @Pointcut in a code-style aspect
			char[] sig = ans[i].resolvedType.signature();
			if (CharOperation.equals(pointcutSig, sig)) {
				if (ans[i].memberValuePairs().length == 0) {
					return ""; // empty pointcut expression
				}
				Expression expr = ans[i].memberValuePairs()[0].value;
				if (expr instanceof StringLiteral) {
					StringLiteral sLit = ((StringLiteral) expr);
					return new String(sLit.source());
				} else if (expr instanceof NameReference && (((NameReference) expr).binding instanceof FieldBinding)) {
					Binding b = ((NameReference) expr).binding;
					Constant c = ((FieldBinding) b).constant();
					return c.stringValue();
				} else {
					throw new BCException("Do not know how to recover pointcut definition from " + expr + " (type "
							+ expr.getClass().getName() + ")");
				}
			}
		}
		return "";
	}

	private boolean isAnnotationStylePointcut(Annotation[] annotations) {
		if (annotations == null) {
			return false;
		}
		for (int i = 0; i < annotations.length; i++) {
			if (annotations[i].resolvedType == null) {
				continue; // XXX happens if we do this very early from
			}
			// buildInterTypeandPerClause
			// may prevent us from resolving references made in @Pointcuts to
			// an @Pointcut in a code-style aspect
			char[] sig = annotations[i].resolvedType.signature();
			if (CharOperation.equals(pointcutSig, sig)) {
				return true;
			}
		}
		return false;
	}

	public WeaverStateInfo getWeaverState() {
		return null;
	}

	public ResolvedType getSuperclass() {
		if (binding.isInterface()) {
			return getResolvedTypeX().getWorld().getCoreType(UnresolvedType.OBJECT);
		}
		// XXX what about java.lang.Object
		return eclipseWorld().fromEclipse(binding.superclass());
	}

	public ResolvedType[] getDeclaredInterfaces() {
		return eclipseWorld().fromEclipse(binding.superInterfaces());
	}

	protected void fillDeclaredMembers() {
		List<ResolvedMember> declaredPointcuts = new ArrayList<ResolvedMember>();
		List<ResolvedMember> declaredMethods = new ArrayList<ResolvedMember>();
		List<ResolvedMember> declaredFields = new ArrayList<ResolvedMember>();

		MethodBinding[] ms = binding.methods(); // the important side-effect of this call is to make
		// sure bindings are completed
		AbstractMethodDeclaration[] methods = declaration.methods;
		if (methods != null) {
			for (int i = 0, len = methods.length; i < len; i++) {
				AbstractMethodDeclaration amd = methods[i];
				if (amd == null || amd.ignoreFurtherInvestigation) {
					continue;
				}
				if (amd instanceof PointcutDeclaration) {
					PointcutDeclaration d = (PointcutDeclaration) amd;
					ResolvedPointcutDefinition df = d.makeResolvedPointcutDefinition(factory);
					if (df != null) {
						declaredPointcuts.add(df);
					}
				} else if (amd instanceof InterTypeDeclaration) {
					// these are handled in a separate pass
					continue;
				} else if (amd instanceof DeclareDeclaration && !(amd instanceof DeclareAnnotationDeclaration)) { // surfaces
					// the
					// annotated
					// ajc$ method
					// these are handled in a separate pass
					continue;
				} else if (amd instanceof AdviceDeclaration) {
					// these are ignored during compilation and only used during
					// weaving
					continue;
				} else if ((amd.annotations != null) && isAnnotationStylePointcut(amd.annotations)) {
					// consider pointcuts defined via annotations
					ResolvedPointcutDefinition df = makeResolvedPointcutDefinition(amd);
					if (df != null) {
						declaredPointcuts.add(df);
					}
				} else {
					if (amd.binding == null || !amd.binding.isValidBinding()) {
						continue;
					}
					ResolvedMember member = factory.makeResolvedMember(amd.binding);
					if (unit != null) {
						boolean positionKnown = true;
						if (amd.binding.sourceMethod() == null) {
							if (amd.binding.declaringClass instanceof SourceTypeBinding) {
								SourceTypeBinding stb = ((SourceTypeBinding) amd.binding.declaringClass);
								if (stb.scope == null || stb.scope.referenceContext == null) {
									positionKnown = false;
								}
							}
						}
						if (positionKnown) { // pr229829
							member.setSourceContext(new EclipseSourceContext(unit.compilationResult, amd.binding.sourceStart()));
							member.setPosition(amd.binding.sourceStart(), amd.binding.sourceEnd());
						} else {
							member.setSourceContext(new EclipseSourceContext(unit.compilationResult, 0));
							member.setPosition(0, 0);
						}
					}
					declaredMethods.add(member);
				}
			}
		}
		
		if (isEnum()) {
			// The bindings for the eclipse binding will include values/valueof
			for (int m=0,len=ms.length;m<len;m++) {
				MethodBinding mb = ms[m];
				if ((mb instanceof SyntheticMethodBinding) && mb.isStatic()) { // cannot use .isSynthetic() because it isn't truly synthetic
					if (CharOperation.equals(mb.selector,valuesCharArray) && mb.parameters.length==0 && mb.returnType.isArrayType() && ((ArrayBinding)mb.returnType).leafComponentType()==binding) {
						// static <EnumType>[] values()
						ResolvedMember valuesMember = factory.makeResolvedMember(mb);
						valuesMember.setSourceContext(new EclipseSourceContext(unit.compilationResult, 0));
						valuesMember.setPosition(0, 0);
						declaredMethods.add(valuesMember);
					} else if (CharOperation.equals(mb.selector,valueOfCharArray) && mb.parameters.length==1 && CharOperation.equals(mb.parameters[0].signature(),jlString) && mb.returnType==binding) {
						// static <EnumType> valueOf(String)
						ResolvedMember valueOfMember = factory.makeResolvedMember(mb);
						valueOfMember.setSourceContext(new EclipseSourceContext(unit.compilationResult, 0));
						valueOfMember.setPosition(0, 0);
						declaredMethods.add(valueOfMember);
					}
				}
			}
		}

		FieldBinding[] fields = binding.fields();
		for (int i = 0, len = fields.length; i < len; i++) {
			FieldBinding f = fields[i];
			declaredFields.add(factory.makeResolvedMember(f));
		}

		this.declaredPointcuts = declaredPointcuts.toArray(new ResolvedPointcutDefinition[declaredPointcuts.size()]);
		this.declaredMethods = declaredMethods.toArray(new ResolvedMember[declaredMethods.size()]);
		this.declaredFields = declaredFields.toArray(new ResolvedMember[declaredFields.size()]);
	}
	
	private final static char[] valuesCharArray = "values".toCharArray();
	private final static char[] valueOfCharArray = "valueOf".toCharArray();
	private final static char[] jlString = "Ljava/lang/String;".toCharArray();
	

	private ResolvedPointcutDefinition makeResolvedPointcutDefinition(AbstractMethodDeclaration md) {
		if (md.binding == null) {
			return null; // there is another error that has caused this...
			// pr138143
		}

		EclipseSourceContext eSourceContext = new EclipseSourceContext(md.compilationResult);
		Pointcut pc = null;
		if (!md.isAbstract()) {
			String expression = getPointcutStringFromAnnotationStylePointcut(md);
			try {
				pc = new PatternParser(expression, eSourceContext).parsePointcut();
			} catch (ParserException pe) { // error will be reported by other
				// means...
				pc = Pointcut.makeMatchesNothing(Pointcut.SYMBOLIC);
			}
		}

		FormalBinding[] bindings = buildFormalAdviceBindingsFrom(md);

		ResolvedPointcutDefinition rpd = new LazyResolvedPointcutDefinition(factory.fromBinding(md.binding.declaringClass),
				md.modifiers, new String(md.selector), factory.fromBindings(md.binding.parameters),
				factory.fromBinding(md.binding.returnType), pc, new EclipseScope(bindings, md.scope));

		rpd.setPosition(md.sourceStart, md.sourceEnd);
		rpd.setSourceContext(eSourceContext);
		return rpd;
	}

	private static final char[] joinPoint = "Lorg/aspectj/lang/JoinPoint;".toCharArray();
	private static final char[] joinPointStaticPart = "Lorg/aspectj/lang/JoinPoint$StaticPart;".toCharArray();
	private static final char[] joinPointEnclosingStaticPart = "Lorg/aspectj/lang/JoinPoint$EnclosingStaticPart;".toCharArray();
	private static final char[] proceedingJoinPoint = "Lorg/aspectj/lang/ProceedingJoinPoint;".toCharArray();

	private FormalBinding[] buildFormalAdviceBindingsFrom(AbstractMethodDeclaration mDecl) {
		if (mDecl.arguments == null) {
			return new FormalBinding[0];
		}
		if (mDecl.binding == null) {
			return new FormalBinding[0];
		}
		EclipseFactory factory = EclipseFactory.fromScopeLookupEnvironment(mDecl.scope);
		String extraArgName = "";// maybeGetExtraArgName();
		FormalBinding[] ret = new FormalBinding[mDecl.arguments.length];
		for (int i = 0; i < mDecl.arguments.length; i++) {
			Argument arg = mDecl.arguments[i];
			String name = new String(arg.name);
			TypeBinding argTypeBinding = mDecl.binding.parameters[i];
			UnresolvedType type = factory.fromBinding(argTypeBinding);
			if (CharOperation.equals(joinPoint, argTypeBinding.signature())
					|| CharOperation.equals(joinPointStaticPart, argTypeBinding.signature())
					|| CharOperation.equals(joinPointEnclosingStaticPart, argTypeBinding.signature())
					|| CharOperation.equals(proceedingJoinPoint, argTypeBinding.signature()) || name.equals(extraArgName)) {
				ret[i] = new FormalBinding.ImplicitFormalBinding(type, name, i);
			} else {
				ret[i] = new FormalBinding(type, name, i, arg.sourceStart, arg.sourceEnd);
			}
		}
		return ret;
	}

	/**
	 * This method may not return all fields, for example it may not include the ajc$initFailureCause or ajc$perSingletonInstance
	 * fields - see bug 129613
	 */
	public ResolvedMember[] getDeclaredFields() {
		if (declaredFields == null) {
			fillDeclaredMembers();
		}
		return declaredFields;
	}

	/**
	 * This method may not return all methods, for example it may not include clinit, aspectOf, hasAspect or ajc$postClinit methods
	 * - see bug 129613
	 */
	public ResolvedMember[] getDeclaredMethods() {
		if (declaredMethods == null) {
			fillDeclaredMembers();
		}
		return declaredMethods;
	}

	public ResolvedMember[] getDeclaredPointcuts() {
		if (declaredPointcuts == null) {
			fillDeclaredMembers();
		}
		return declaredPointcuts;
	}

	public int getModifiers() {
		// only return the real Java modifiers, not the extra eclipse ones
		return binding.modifiers & ExtraCompilerModifiers.AccJustFlag;
	}

	public String toString() {
		return "EclipseSourceType(" + new String(binding.sourceName()) + ")";
	}

	// XXX make sure this is applied to classes and interfaces
	public void checkPointcutDeclarations() {
		ResolvedMember[] pointcuts = getDeclaredPointcuts();
		boolean sawError = false;
		for (int i = 0, len = pointcuts.length; i < len; i++) {
			if (pointcuts[i] == null) {
				// Something else is broken in this file and will be reported separately
				continue;
			}
			if (pointcuts[i].isAbstract()) {
				if (!this.isAspect()) {
					eclipseWorld().showMessage(IMessage.ERROR, "The abstract pointcut " + pointcuts[i].getName()+ " can only be defined in an aspect",
							pointcuts[i].getSourceLocation(), null);
					sawError = true;
				} else if (!binding.isAbstract()) {
					eclipseWorld().showMessage(IMessage.ERROR, "abstract pointcut in concrete aspect: " + pointcuts[i],
							pointcuts[i].getSourceLocation(), null);
					sawError = true;
				}
			}

			for (int j = i + 1; j < len; j++) {
				if (pointcuts[j] == null) {
					// Something else is broken in this file and will be reported separately
					continue;
				}
				if (pointcuts[i].getName().equals(pointcuts[j].getName())) {
					eclipseWorld().showMessage(IMessage.ERROR, "duplicate pointcut name: " + pointcuts[j].getName(),
							pointcuts[i].getSourceLocation(), pointcuts[j].getSourceLocation());
					sawError = true;
				}
			}
		}

		// now check all inherited pointcuts to be sure that they're handled
		// reasonably
		if (sawError || !isAspect()) {
			return;
		}

		// find all pointcuts that override ones from super and check override
		// is legal
		// i.e. same signatures and greater or equal visibility
		// find all inherited abstract pointcuts and make sure they're
		// concretized if I'm concrete
		// find all inherited pointcuts and make sure they don't conflict
		getResolvedTypeX().getExposedPointcuts(); // ??? this is an odd
		// construction

	}

	// ???
	// public CrosscuttingMembers collectCrosscuttingMembers() {
	// return crosscuttingMembers;
	// }

	// public ISourceLocation getSourceLocation() {
	// TypeDeclaration dec = binding.scope.referenceContext;
	// return new EclipseSourceLocation(dec.compilationResult, dec.sourceStart,
	// dec.sourceEnd);
	// }

	public boolean isInterface() {
		return binding.isInterface();
	}

	// XXXAJ5: Should be constants in the eclipse compiler somewhere, once it
	// supports 1.5
	public final static short ACC_ANNOTATION = 0x2000;
	public final static short ACC_ENUM = 0x4000;

	public boolean isEnum() {
		return (binding.getAccessFlags() & ACC_ENUM) != 0;
	}

	public boolean isAnnotation() {
		return (binding.getAccessFlags() & ACC_ANNOTATION) != 0;
	}

	public boolean isAnnotationWithRuntimeRetention() {
		if (!isAnnotation()) {
			return false;
		} else {
			return (binding.getAnnotationTagBits() & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
		}
	}

	public String getRetentionPolicy() {
		if (isAnnotation()) {
			if ((binding.getAnnotationTagBits() & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention) {
				return "RUNTIME";
			}
			if ((binding.getAnnotationTagBits() & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationSourceRetention) {
				return "SOURCE";
			}
			if ((binding.getAnnotationTagBits() & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationClassRetention) {
				return "CLASS";
			}
		}
		return null;
	}

	public boolean canAnnotationTargetType() {
		if (isAnnotation()) {
			return ((binding.getAnnotationTagBits() & TagBits.AnnotationForType) != 0);
		}
		return false;
	}

	public AnnotationTargetKind[] getAnnotationTargetKinds() {
		if (discoveredAnnotationTargetKinds) {
			return annotationTargetKinds;
		}
		discoveredAnnotationTargetKinds = true;
		annotationTargetKinds = null; // null means we have no idea or the
		// @Target annotation hasn't been used
		// if (isAnnotation()) {
		// Annotation[] annotationsOnThisType = declaration.annotations;
		// if (annotationsOnThisType != null) {
		// for (int i = 0; i < annotationsOnThisType.length; i++) {
		// Annotation a = annotationsOnThisType[i];
		// if (a.resolvedType != null) {
		// String packageName = new
		// String(a.resolvedType.qualifiedPackageName()).concat(".");
		// String sourceName = new String(a.resolvedType.qualifiedSourceName());
		// if ((packageName +
		// sourceName).equals(UnresolvedType.AT_TARGET.getName())) {
		// MemberValuePair[] pairs = a.memberValuePairs();
		// for (int j = 0; j < pairs.length; j++) {
		// MemberValuePair pair = pairs[j];
		// targetKind = pair.value.toString();
		// return targetKind;
		// }
		// }
		// }
		// }
		// }
		// }
		// return targetKind;
		if (isAnnotation()) {
			List<AnnotationTargetKind> targetKinds = new ArrayList<AnnotationTargetKind>();

			if ((binding.getAnnotationTagBits() & TagBits.AnnotationForAnnotationType) != 0) {
				targetKinds.add(AnnotationTargetKind.ANNOTATION_TYPE);
			}
			if ((binding.getAnnotationTagBits() & TagBits.AnnotationForConstructor) != 0) {
				targetKinds.add(AnnotationTargetKind.CONSTRUCTOR);
			}
			if ((binding.getAnnotationTagBits() & TagBits.AnnotationForField) != 0) {
				targetKinds.add(AnnotationTargetKind.FIELD);
			}
			if ((binding.getAnnotationTagBits() & TagBits.AnnotationForLocalVariable) != 0) {
				targetKinds.add(AnnotationTargetKind.LOCAL_VARIABLE);
			}
			if ((binding.getAnnotationTagBits() & TagBits.AnnotationForMethod) != 0) {
				targetKinds.add(AnnotationTargetKind.METHOD);
			}
			if ((binding.getAnnotationTagBits() & TagBits.AnnotationForPackage) != 0) {
				targetKinds.add(AnnotationTargetKind.PACKAGE);
			}
			if ((binding.getAnnotationTagBits() & TagBits.AnnotationForParameter) != 0) {
				targetKinds.add(AnnotationTargetKind.PARAMETER);
			}
			if ((binding.getAnnotationTagBits() & TagBits.AnnotationForType) != 0) {
				targetKinds.add(AnnotationTargetKind.TYPE);
			}

			if (!targetKinds.isEmpty()) {
				annotationTargetKinds = new AnnotationTargetKind[targetKinds.size()];
				return targetKinds.toArray(annotationTargetKinds);
			}
		}
		return annotationTargetKinds;
	}

	/**
	 * Ensure the annotation types have been resolved, where resolved means the eclipse type bindings have been converted to their
	 * ResolvedType representations. This does not deeply resolve the annotations, it only does the type names.
	 */
	private void ensureAnnotationTypesResolved() {
		// may need to re-resolve if new annotations have been added
		int declarationAnnoCount = (declaration.annotations == null ? 0 : declaration.annotations.length);
		if (!annotationTypesAreResolved || declarationAnnoCount != annotationTypes.length) {
			Annotation[] as = declaration.annotations;
			if (as == null) {
				annotationTypes = ResolvedType.NONE;
			} else {
				annotationTypes = new ResolvedType[as.length];
				for (int a = 0; a < as.length; a++) {
					TypeBinding tb = as[a].type.resolveType(declaration.staticInitializerScope);
					if (tb == null) {
						annotationTypes[a] = ResolvedType.MISSING;
					} else {
						annotationTypes[a] = factory.fromTypeBindingToRTX(tb);
					}
				}
			}
			annotationTypesAreResolved = true;
		}
	}

	public boolean hasAnnotation(UnresolvedType ofType) {
		ensureAnnotationTypesResolved();
		for (int a = 0, max = annotationTypes.length; a < max; a++) {
			if (ofType.equals(annotationTypes[a])) {
				return true;
			}
		}
		return false;
	}

	/**
	 * WARNING: This method does not have a complete implementation.
	 * 
	 * The aim is that it converts Eclipse annotation objects to the AspectJ form of annotations (the type AnnotationAJ). The
	 * AnnotationX objects returned are wrappers over either a Bcel annotation type or the AspectJ AnnotationAJ type. The minimal
	 * implementation provided here is for processing the RetentionPolicy and Target annotation types - these are the only ones
	 * which the weaver will attempt to process from an EclipseSourceType.
	 * 
	 * More notes: The pipeline has required us to implement this. With the pipeline we can be weaving a type and asking questions
	 * of annotations before they have been turned into Bcel objects - ie. when they are still in EclipseSourceType form. Without
	 * the pipeline we would have converted everything to Bcel objects before proceeding with weaving. Because the pipeline won't
	 * start weaving until all aspects have been compiled and the fact that no AspectJ constructs match on the values within
	 * annotations, this code only needs to deal with converting system annotations that the weaver needs to process
	 * (RetentionPolicy, Target).
	 */
	public AnnotationAJ[] getAnnotations() {
		int declarationAnnoCount = (declaration.annotations == null ? 0 : declaration.annotations.length);
		if (annotations != null && annotations.length == declarationAnnoCount) {
			return annotations; // only do this once
		}
		if (!annotationsFullyResolved || annotations.length!=declarationAnnoCount) {
			TypeDeclaration.resolveAnnotations(declaration.staticInitializerScope, declaration.annotations, binding);
			annotationsFullyResolved = true;
		}
		Annotation[] as = declaration.annotations;
		if (as == null || as.length == 0) {
			annotations = AnnotationAJ.EMPTY_ARRAY;
		} else {
			annotations = new AnnotationAJ[as.length];
			for (int i = 0; i < as.length; i++) {
				annotations[i] = convertEclipseAnnotation(as[i], factory.getWorld());
			}
		}
		return annotations;
	}
	
	public boolean hasAnnotations() {
		return (declaration.annotations != null && declaration.annotations.length != 0);
	}

	/**
	 * Convert one eclipse annotation into an AnnotationX object containing an AnnotationAJ object.
	 * 
	 * This code and the helper methods used by it will go *BANG* if they encounter anything not currently supported - this is safer
	 * than limping along with a malformed annotation. When the *BANG* is encountered the bug reporter should indicate the kind of
	 * annotation they were working with and this code can be enhanced to support it.
	 */
	public AnnotationAJ convertEclipseAnnotation(Annotation eclipseAnnotation, World w) {
		// TODO if it is sourcevisible, we shouldn't let it through!!!!!!!!!
		// testcase!
		ResolvedType annotationType = factory.fromTypeBindingToRTX(eclipseAnnotation.type.resolvedType);
		// long bs = (eclipseAnnotation.bits & TagBits.AnnotationRetentionMASK);
		boolean isRuntimeVisible = (eclipseAnnotation.bits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
		StandardAnnotation annotationAJ = new StandardAnnotation(annotationType, isRuntimeVisible);
		generateAnnotation(eclipseAnnotation, annotationAJ, w);
		return annotationAJ;
	}

	static class MissingImplementationException extends RuntimeException {
		MissingImplementationException(String reason) {
			super(reason);
		}
	}

	/**
	 * Use the information in the supplied eclipse based annotation to fill in the standard annotation.
	 * 
	 * @param annotation eclipse based annotation representation
	 * @param annotationAJ AspectJ based annotation representation
	 */
	private void generateAnnotation(Annotation annotation, StandardAnnotation annotationAJ, World w) {
		if (annotation instanceof NormalAnnotation) {
			NormalAnnotation normalAnnotation = (NormalAnnotation) annotation;
			MemberValuePair[] memberValuePairs = normalAnnotation.memberValuePairs;
			if (memberValuePairs != null) {
				int memberValuePairsLength = memberValuePairs.length;
				for (int i = 0; i < memberValuePairsLength; i++) {
					MemberValuePair memberValuePair = memberValuePairs[i];
					MethodBinding methodBinding = memberValuePair.binding;
					if (methodBinding == null) {
						// is this just a marker annotation?
						if (memberValuePair.value instanceof MarkerAnnotation) {
							MarkerAnnotation eMarkerAnnotation = (MarkerAnnotation) memberValuePair.value;
							AnnotationBinding eMarkerAnnotationBinding = eMarkerAnnotation.getCompilerAnnotation();
							ReferenceBinding eAnnotationType = eMarkerAnnotationBinding.getAnnotationType();
							ResolvedType ajAnnotationType = factory.fromTypeBindingToRTX(eAnnotationType);
							boolean isRuntimeVisible = (eMarkerAnnotation.bits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
							StandardAnnotation ajAnnotation = new StandardAnnotation(ajAnnotationType, isRuntimeVisible);
							AnnotationValue av = new AnnotationAnnotationValue(ajAnnotation);
							AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(memberValuePair.name), av);
							annotationAJ.addNameValuePair(anvp);
							// } else if (memberValuePair.value instanceof NormalAnnotation) {
							// NormalAnnotation eNormalAnnotation = (NormalAnnotation) memberValuePair.value;
							// AnnotationBinding eMarkerAnnotationBinding = eNormalAnnotation.getCompilerAnnotation();
							// ReferenceBinding eAnnotationType = eMarkerAnnotationBinding.getAnnotationType();
							// ResolvedType ajAnnotationType = factory.fromTypeBindingToRTX(eAnnotationType);
							// boolean isRuntimeVisible = (eNormalAnnotation.bits & TagBits.AnnotationRetentionMASK) ==
							// TagBits.AnnotationRuntimeRetention;
							// StandardAnnotation ajAnnotation = new StandardAnnotation(ajAnnotationType, isRuntimeVisible);
							// MemberValuePair[] pairs = eNormalAnnotation.memberValuePairs;
							// if (pairs != null) {
							// for (int p = 0; p < pairs.length; p++) {
							// MemberValuePair pair = pairs[p];
							// throw new IllegalStateException("nyi");
							//
							// }
							// }
							// AnnotationValue av = new AnnotationAnnotationValue(ajAnnotation);
							// AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(memberValuePair.name), av);
							// annotationAJ.addNameValuePair(anvp);
						} else if (memberValuePair.value instanceof Literal) {
							AnnotationValue av = generateElementValue(memberValuePair.value,
									((Literal) memberValuePair.value).resolvedType);
							AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(memberValuePair.name), av);
							annotationAJ.addNameValuePair(anvp);
						} else if (memberValuePair.value instanceof ArrayInitializer) {
							ArrayInitializer arrayInitializer = (ArrayInitializer) memberValuePair.value;
							Expression[] expressions = arrayInitializer.expressions;
							AnnotationValue[] arrayValues = new AnnotationValue[expressions.length];
							for (int e = 0; e < expressions.length; e++) {
								arrayValues[e] = generateElementValue(expressions[e],
										((ArrayBinding) arrayInitializer.resolvedType).leafComponentType);
							}
							AnnotationValue array = new ArrayAnnotationValue(arrayValues);
							AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(memberValuePair.name), array);
							annotationAJ.addNameValuePair(anvp);
						} else {
							throw new MissingImplementationException(
									"Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation ["
											+ annotation + "]");
						}
					} else {
						AnnotationValue av = generateElementValue(memberValuePair.value, methodBinding.returnType);
						AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(memberValuePair.name), av);
						annotationAJ.addNameValuePair(anvp);
					}
				}
			}
		} else if (annotation instanceof SingleMemberAnnotation) {
			// this is a single member annotation (one member value)
			SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) annotation;
			MemberValuePair mvp = singleMemberAnnotation.memberValuePairs()[0];
			if (mvp.value instanceof ArrayInitializer) {
				ArrayInitializer arrayInitializer = (ArrayInitializer) mvp.value;
				Expression[] expressions = arrayInitializer.expressions;
				AnnotationValue[] arrayValues = new AnnotationValue[expressions.length];
				for (int e = 0; e < expressions.length; e++) {
					arrayValues[e] = generateElementValue(expressions[e],
							((ArrayBinding) arrayInitializer.resolvedType).leafComponentType);
				}
				AnnotationValue array = new ArrayAnnotationValue(arrayValues);
				AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(mvp.name), array);
				annotationAJ.addNameValuePair(anvp);
			} else if (mvp.value instanceof Literal) {
				AnnotationValue av = generateElementValue(mvp.value,
						((Literal) mvp.value).resolvedType);
				AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(mvp.name), av);
				annotationAJ.addNameValuePair(anvp);
			} else {
				MethodBinding methodBinding = mvp.binding;
				if (methodBinding == null) {
					throw new MissingImplementationException(
							"Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation [" + annotation + "]");
				} else {
					AnnotationValue av = generateElementValue(singleMemberAnnotation.memberValue, methodBinding.returnType);
					annotationAJ.addNameValuePair(new AnnotationNameValuePair(new String(
							singleMemberAnnotation.memberValuePairs()[0].name), av));
				}
			}
		} else if (annotation instanceof MarkerAnnotation) {
			return;
		} else {
			// this is something else...
			throw new MissingImplementationException(
					"Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation [" + annotation + "]");
		}
	}

	private AnnotationValue generateElementValue(Expression defaultValue, TypeBinding memberValuePairReturnType) {
		Constant constant = defaultValue.constant;
		TypeBinding defaultValueBinding = defaultValue.resolvedType;
		if (defaultValueBinding == null) {
			throw new MissingImplementationException(
					"Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value [" + defaultValue
							+ "]");
		} else {
			if (memberValuePairReturnType.isArrayType() && !defaultValueBinding.isArrayType()) {
				if (constant != null && constant != Constant.NotAConstant) {
					// Testcase for this clause is MultiProjectIncrementalTests.testAnnotations_pr262154()
					AnnotationValue av = EclipseAnnotationConvertor.generateElementValueForConstantExpression(defaultValue,
							defaultValueBinding);
					return new ArrayAnnotationValue(new AnnotationValue[] { av });
				} else {
					AnnotationValue av = generateElementValueForNonConstantExpression(defaultValue, defaultValueBinding);
					return new ArrayAnnotationValue(new AnnotationValue[] { av });
				}
			} else {
				if (constant != null && constant != Constant.NotAConstant) {
					AnnotationValue av = EclipseAnnotationConvertor.generateElementValueForConstantExpression(defaultValue,
							defaultValueBinding);
					if (av == null) {
						throw new MissingImplementationException(
								"Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value ["
										+ defaultValue + "]");
					}
					return av;
					// generateElementValue(attributeOffset, defaultValue,
					// constant, memberValuePairReturnType.leafComponentType());
				} else {
					AnnotationValue av = generateElementValueForNonConstantExpression(defaultValue, defaultValueBinding);
					return av;
				}
			}
		}
	}

	private AnnotationValue generateElementValueForNonConstantExpression(Expression defaultValue, TypeBinding defaultValueBinding) {
		if (defaultValueBinding != null) {
			if (defaultValueBinding.isEnum()) {
				FieldBinding fieldBinding = null;
				if (defaultValue instanceof QualifiedNameReference) {
					QualifiedNameReference nameReference = (QualifiedNameReference) defaultValue;
					fieldBinding = (FieldBinding) nameReference.binding;
				} else if (defaultValue instanceof SingleNameReference) {
					SingleNameReference nameReference = (SingleNameReference) defaultValue;
					fieldBinding = (FieldBinding) nameReference.binding;
				} else {
					throw new MissingImplementationException(
							"Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value ["
									+ defaultValue + "]");
				}
				if (fieldBinding != null) {
					String sig = new String(fieldBinding.type.signature());
					AnnotationValue enumValue = new EnumAnnotationValue(sig, new String(fieldBinding.name));
					return enumValue;
				}
				throw new MissingImplementationException(
						"Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value [" + defaultValue
								+ "]");
			} else if (defaultValue instanceof ClassLiteralAccess) {
				ClassLiteralAccess cla = (ClassLiteralAccess)defaultValue;
				TypeBinding claTargetType = cla.targetType;
//				ResolvedType classLiteralType = factory.fromTypeBindingToRTX(defaultValueBinding);
				String classLiteralSig = new String(claTargetType.signature());
				AnnotationValue classValue = new ClassAnnotationValue(classLiteralSig);
				return classValue;
			} else if (defaultValueBinding.isAnnotationType()) {
				if (defaultValue instanceof MarkerAnnotation) {
					ResolvedType ajAnnotationType = factory.fromTypeBindingToRTX(defaultValueBinding);
					StandardAnnotation ajAnnotation = new StandardAnnotation(ajAnnotationType,
							ajAnnotationType.isAnnotationWithRuntimeRetention());
					AnnotationValue av = new AnnotationAnnotationValue(ajAnnotation);
					return av;
				} else if (defaultValue instanceof NormalAnnotation) {
					NormalAnnotation normalAnnotation = (NormalAnnotation) defaultValue;
					ResolvedType ajAnnotationType = factory.fromTypeBindingToRTX(defaultValueBinding);
					StandardAnnotation ajAnnotation = new StandardAnnotation(ajAnnotationType,
							ajAnnotationType.isAnnotationWithRuntimeRetention());
					MemberValuePair[] pairs = normalAnnotation.memberValuePairs;
					if (pairs != null) {
						for (int p = 0; p < pairs.length; p++) {
							MemberValuePair pair = pairs[p];
							Expression valueEx = pair.value;
							AnnotationValue pairValue = null;
							if (valueEx instanceof Literal) {
								pairValue = generateElementValue(valueEx, ((Literal) valueEx).resolvedType);
							} else {
								pairValue = generateElementValue(pair.value, pair.binding.returnType);
							}
							ajAnnotation.addNameValuePair(new AnnotationNameValuePair(new String(pair.name), pairValue));
						}
					}
					AnnotationValue av = new AnnotationAnnotationValue(ajAnnotation);
					return av;
				} else {
					throw new MissingImplementationException(
							"Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value ["
									+ defaultValue + "]");
				}
			} else if (defaultValueBinding.isArrayType()) {
				// array type
				if (defaultValue instanceof ArrayInitializer) {
					ArrayInitializer arrayInitializer = (ArrayInitializer) defaultValue;
					int arrayLength = arrayInitializer.expressions != null ? arrayInitializer.expressions.length : 0;
					AnnotationValue[] values = new AnnotationValue[arrayLength];
					for (int i = 0; i < arrayLength; i++) {
						values[i] = generateElementValue(arrayInitializer.expressions[i], defaultValueBinding.leafComponentType());// ,
						// attributeOffset
						// )
						// ;
					}
					ArrayAnnotationValue aav = new ArrayAnnotationValue(values);
					return aav;
				} else {
					throw new MissingImplementationException(
							"Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value ["
									+ defaultValue + "]");
				}
				// } else if (defaultValue instanceof MagicLiteral) {
				// if (defaultValue instanceof FalseLiteral) {
				// new AnnotationValue
				// } else if (defaultValue instanceof TrueLiteral) {
				//
				// } else {
				// throw new MissingImplementationException(
				// "Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value ["
				// +defaultValue+"]");
				// }
			} else {
				// class type
				throw new MissingImplementationException(
						"Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value [" + defaultValue
								+ "]");
				// if (contentsOffset + 3 >= this.contents.length) {
				// resizeContents(3);
				// }
				// contents[contentsOffset++] = (byte) 'c';
				// if (defaultValue instanceof ClassLiteralAccess) {
				// ClassLiteralAccess classLiteralAccess = (ClassLiteralAccess)
				// defaultValue;
				// final int classInfoIndex =
				// constantPool.literalIndex(classLiteralAccess
				// .targetType.signature());
				// contents[contentsOffset++] = (byte) (classInfoIndex >> 8);
				// contents[contentsOffset++] = (byte) classInfoIndex;
				// } else {
				// contentsOffset = attributeOffset;
				// }
			}
		} else {
			throw new MissingImplementationException(
					"Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value [" + defaultValue
							+ "]");
			// contentsOffset = attributeOffset;
		}
	}

	public ResolvedType[] getAnnotationTypes() {
		ensureAnnotationTypesResolved();
		return annotationTypes;
	}

	public PerClause getPerClause() {
		// should probably be: ((AspectDeclaration)declaration).perClause;
		// but we don't need this level of detail, and working with real per
		// clauses
		// at this stage of compilation is not worth the trouble
		if (!isAnnotationStyleAspect()) {
			if (declaration instanceof AspectDeclaration) {
				PerClause pc = ((AspectDeclaration) declaration).perClause;
				if (pc != null) {
					return pc;
				}
			}
			return new PerSingleton();
		} else {
			// for @Aspect, we do need the real kind though we don't need the
			// real perClause
			// at least try to get the right perclause
			PerClause pc = null;
			if (declaration instanceof AspectDeclaration) {
				pc = ((AspectDeclaration) declaration).perClause;
			}
			if (pc == null) {
				PerClause.Kind kind = getPerClauseForTypeDeclaration(declaration);
				// returning a perFromSuper is enough to get the correct kind..
				// (that's really a hack - AV)
				return new PerFromSuper(kind);
			}
			return pc;
		}
	}

	PerClause.Kind getPerClauseForTypeDeclaration(TypeDeclaration typeDeclaration) {
		Annotation[] annotations = typeDeclaration.annotations;
		if (annotations == null) {
			// Can happen if an aspect is extending a regular class
			return null;
		}
		for (int i = 0; i < annotations.length; i++) {
			Annotation annotation = annotations[i];
			if (annotation != null && annotation.resolvedType != null
					&& CharOperation.equals(aspectSig, annotation.resolvedType.signature())) {
				// found @Aspect(...)
				if (annotation.memberValuePairs() == null || annotation.memberValuePairs().length == 0) {
					// it is an @Aspect or @Aspect()
					// needs to use PerFromSuper if declaration extends a super
					// aspect
					PerClause.Kind kind = lookupPerClauseKind(typeDeclaration.binding.superclass);
					// if no super aspect, we have a @Aspect() means singleton
					if (kind == null) {
						return PerClause.SINGLETON;
					} else {
						return kind;
					}
				} else if (annotation instanceof SingleMemberAnnotation) {
					// it is an @Aspect(...something...)
					SingleMemberAnnotation theAnnotation = (SingleMemberAnnotation) annotation;
					String clause = new String(((StringLiteral) theAnnotation.memberValue).source());// TODO
					// cast
					// safe
					// ?
					return determinePerClause(typeDeclaration, clause);
				} else if (annotation instanceof NormalAnnotation) { 
					// this kind if it was added by the visitor!
					// it is an @Aspect(...something...)
					NormalAnnotation theAnnotation = (NormalAnnotation) annotation;
					if (theAnnotation.memberValuePairs == null || theAnnotation.memberValuePairs.length < 1) {
						return PerClause.SINGLETON;
					}
					String clause = new String(((StringLiteral) theAnnotation.memberValuePairs[0].value).source());// TODO
					// cast
					// safe
					// ?
					return determinePerClause(typeDeclaration, clause);
				} else {
					eclipseWorld().showMessage(
							IMessage.ABORT,
							"@Aspect annotation is expected to be SingleMemberAnnotation with 'String value()' as unique element",
							new EclipseSourceLocation(typeDeclaration.compilationResult, typeDeclaration.sourceStart,
									typeDeclaration.sourceEnd), null);
					return PerClause.SINGLETON;// fallback strategy just to avoid NPE
				}
			}
		}
		return null;// no @Aspect annotation at all (not as aspect)
	}

	private PerClause.Kind determinePerClause(TypeDeclaration typeDeclaration, String clause) {
		if (clause.startsWith("perthis(")) {
			return PerClause.PEROBJECT;
		} else if (clause.startsWith("pertarget(")) {
			return PerClause.PEROBJECT;
		} else if (clause.startsWith("percflow(")) {
			return PerClause.PERCFLOW;
		} else if (clause.startsWith("percflowbelow(")) {
			return PerClause.PERCFLOW;
		} else if (clause.startsWith("pertypewithin(")) {
			return PerClause.PERTYPEWITHIN;
		} else if (clause.startsWith("issingleton(")) {
			return PerClause.SINGLETON;
		} else {
			eclipseWorld().showMessage(
					IMessage.ABORT,
					"cannot determine perClause '" + clause + "'",
					new EclipseSourceLocation(typeDeclaration.compilationResult, typeDeclaration.sourceStart,
							typeDeclaration.sourceEnd), null);
			return PerClause.SINGLETON;// fallback strategy just to avoid NPE
		}
	}

	// adapted from AspectDeclaration
	private PerClause.Kind lookupPerClauseKind(ReferenceBinding binding) {
		final PerClause.Kind kind;
		if (binding instanceof BinaryTypeBinding) {
			ResolvedType superTypeX = factory.fromEclipse(binding);
			PerClause perClause = superTypeX.getPerClause();
			// clause is null for non aspect classes since coming from BCEL
			// attributes
			if (perClause != null) {
				kind = superTypeX.getPerClause().getKind();
			} else {
				kind = null;
			}
		} else if (binding instanceof SourceTypeBinding) {
			SourceTypeBinding sourceSc = (SourceTypeBinding) binding;
			if (sourceSc.scope.referenceContext instanceof AspectDeclaration) {
				// code style
				kind = ((AspectDeclaration) sourceSc.scope.referenceContext).perClause.getKind();
			} else { // if (sourceSc.scope.referenceContext instanceof
				// TypeDeclaration) {
				// if @Aspect: perFromSuper, else if @Aspect(..) get from anno
				// value, else null
				kind = getPerClauseForTypeDeclaration((sourceSc.scope.referenceContext));
			}
		} else {
			// XXX need to handle this too
			kind = null;
		}
		return kind;
	}

	public Collection getDeclares() {
		return declares;
	}

	public Collection getPrivilegedAccesses() {
		return Collections.EMPTY_LIST;
	}

	public Collection getTypeMungers() {
		return typeMungers;
	}

	public boolean doesNotExposeShadowMungers() {
		return true;
	}

	public String getDeclaredGenericSignature() {
		return CharOperation.charToString(binding.genericSignature());
	}

	public boolean isGeneric() {
		return binding.isGenericType();
	}

	public TypeVariable[] getTypeVariables() {
		if (declaration.typeParameters == null) {
			return new TypeVariable[0];
		}
		TypeVariable[] typeVariables = new TypeVariable[declaration.typeParameters.length];
		for (int i = 0; i < typeVariables.length; i++) {
			typeVariables[i] = typeParameter2TypeVariable(declaration.typeParameters[i]);
		}
		return typeVariables;
	}

	private TypeVariable typeParameter2TypeVariable(TypeParameter typeParameter) {
		String name = new String(typeParameter.name);
		ReferenceBinding superclassBinding = typeParameter.binding.superclass;
		UnresolvedType superclass = UnresolvedType.forSignature(new String(superclassBinding.signature()));
		UnresolvedType[] superinterfaces = null;
		ReferenceBinding[] superInterfaceBindings = typeParameter.binding.superInterfaces;
		if (superInterfaceBindings != null) {
			superinterfaces = new UnresolvedType[superInterfaceBindings.length];
			for (int i = 0; i < superInterfaceBindings.length; i++) {
				superinterfaces[i] = UnresolvedType.forSignature(new String(superInterfaceBindings[i].signature()));
			}
		}
		// XXX what about lower binding?
		TypeVariable tv = new TypeVariable(name, superclass, superinterfaces);
		tv.setDeclaringElement(factory.fromBinding(typeParameter.binding.declaringElement));
		tv.setRank(typeParameter.binding.rank);
		return tv;
	}

}
