/*******************************************************************************
 * Copyright (c) 2013, 2017 IBM Corporation.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.jdt.compiler.apt.tests.processors.elements;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.Filer;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.AnnotatedConstruct;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.NoType;
import javax.lang.model.type.NullType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;

import org.eclipse.jdt.compiler.apt.tests.annotations.Foo;
import org.eclipse.jdt.compiler.apt.tests.annotations.FooContainer;
import org.eclipse.jdt.compiler.apt.tests.annotations.FooNonContainer;
import org.eclipse.jdt.compiler.apt.tests.annotations.Goo;
import org.eclipse.jdt.compiler.apt.tests.annotations.GooNonContainer;
import org.eclipse.jdt.compiler.apt.tests.annotations.IFoo;
import org.eclipse.jdt.compiler.apt.tests.annotations.IFooContainer;
import org.eclipse.jdt.compiler.apt.tests.annotations.TFoo;
import org.eclipse.jdt.compiler.apt.tests.annotations.TFooContainer;
import org.eclipse.jdt.compiler.apt.tests.annotations.Type;
import org.eclipse.jdt.compiler.apt.tests.annotations.Type$1;
import org.eclipse.jdt.compiler.apt.tests.processors.base.BaseProcessor;

/**
 * A processor that explores the java 8 specific elements and validates the lambda and 
 * type annotated elements. To enable this processor, add 
 * -Aorg.eclipse.jdt.compiler.apt.tests.processors.elements.Java8ElementProcessor to the command line.
 * @since 3.10
 */
@SupportedAnnotationTypes({"targets.model8.TypeAnnot",
							"org.eclipse.jdt.compiler.apt.tests.annotations.Type", "org.eclipse.jdt.compiler.apt.tests.annotations.Type1",
							"org.eclipse.jdt.compiler.apt.tests.annotations.Type$1", 
	                       "org.eclipse.jdt.compiler.apt.tests.annotations.Foo", "org.eclipse.jdt.compiler.apt.tests.annotations.FooContainer",
	                       "org.eclipse.jdt.compiler.apt.tests.annotations.IFoo", "org.eclipse.jdt.compiler.apt.tests.annotations.IFooContainer",
	                       "org.eclipse.jdt.compiler.apt.tests.annotations.Goo", "org.eclipse.jdt.compiler.apt.tests.annotations.GooNonContainer",
	                       "org.eclipse.jdt.compiler.apt.tests.annotations.FooNonContainer", "targets.filer8.PackageAnnot"})

@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class Java8ElementProcessor extends BaseProcessor {
	
	private static final String[] ELEMENT_NAMES = new String[] {"targets.model8.X", "T", "U", "K", "V", "KK", "VV", "KKK", "VVV"};
	private static final String[] TYPE_PARAM_ELEMENTS_Z1 = new String[] {"KK", "VV"};
	private static final String[] TYPE_PARAM_ELEMENTS_Z2 = new String[] {"KKK", "VVV"};
	String simpleName = "filer8";
	String packageName = "targets.filer8";
	int roundNo = 0;
	boolean reportSuccessAlready = true;
		
	protected RoundEnvironment roundEnv = null;
	// Always return false from this processor, because it supports "*".
	// The return value does not signify success or failure!
	@Override
	public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
		if (roundEnv.processingOver()) {
			return false;
		}
		
		this.roundEnv = roundEnv;

		Map<String, String> options = processingEnv.getOptions();
		if (!options.containsKey(this.getClass().getName())) {
			// Disable this processor unless we are intentionally performing the test.
			return false;
		} else {
			try {
				if (!invokeTestMethods(options)) {
					testAll();
				}
				if (this.reportSuccessAlready) {
					super.reportSuccess();
				}
			} catch (AssertionFailedError e) {
				super.reportError(getExceptionStackTrace(e));
			} catch (Throwable e) {
				e.printStackTrace();
			}
		}
		return false;
	}

	public boolean invokeTestMethods(Map<String, String> options) throws Throwable {
		Method testMethod = null;
		Set<String> keys = options.keySet();
		boolean testsFound = false;
		for (String option : keys) {
			if (option.startsWith("test")) {
				try {
					testMethod = this.getClass().getDeclaredMethod(option, new Class[0]);
					if (testMethod != null) {
						testsFound = true;
						testMethod.invoke(this,  new Object[0]);
					}
				} catch (InvocationTargetException e) {
					throw e.getCause();
				} catch (Exception e) {
					super.reportError(getExceptionStackTrace(e));
				}
			}
		}
		return testsFound;
	}

	public void testAll() throws AssertionFailedError {
		testSE8Specifics();
		testLambdaSpecifics();
		testTypeAnnotations();
		testTypeAnnotations1();
		testTypeAnnotations2();
		testTypeAnnotations3();
		testTypeAnnotations4();
		testTypeAnnotations5();
		testTypeAnnotations6();
		testTypeAnnotations7();
		testTypeAnnotations8();
		testTypeAnnotations9();
		testTypeAnnotations10();
		testTypeAnnotations11();
		testTypeAnnotations12();
		testTypeAnnotations13();
		testTypeAnnotations14();
		testTypeAnnotations15();
		testTypeAnnotations16();
		testRepeatedAnnotations17();
		testRepeatedAnnotations18();
		testRepeatedAnnotations19();
		testRepeatedAnnotations20();
		testRepeatedAnnotations21();
		testRepeatedAnnotations22();
		testTypeAnnotations23();
		testRepeatedAnnotations24();
		testRepeatedAnnotations25();
		testTypeAnnotations26();
		testTypeAnnotations27();
		//testPackageAnnotations();
		testBug520540();
		testBug526288();
		testEnumConstArguments();
	}
	
	public void testLambdaSpecifics() {
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.LambdaTest");
		assertNotNull("Java8ElementProcessor#examineLambdaSpecifics: Type element for LambdaTest should not be null", annotatedType);
		assertFalse("Java8ElementProcessor#examineLambdaSpecifics: Type LambdaTest is not a functional interface", _elementUtils.isFunctionalInterface(annotatedType));
		List<? extends Element> members = _elementUtils.getAllMembers(annotatedType);
		ExecutableElement method = null;
		for (ExecutableElement member : ElementFilter.methodsIn(members)) {
			if ("foo".equals(member.getSimpleName().toString())) {
				method = member;
				break;
			}
		}
		assertNotNull("Java8ElementProcessor#examineLambdaSpecifics: Element for method foo should not be null", method);
		assertFalse("Java8ElementProcessor#examineLambdaSpecifics: Method foo is not a default method", method.isDefault());
		Set<Modifier> modifiers = method.getModifiers();
		assertModifiers(modifiers, new String[]{});

		annotatedType = _elementUtils.getTypeElement("targets.model8.DefaultInterface");
		assertNotNull("Java8ElementProcessor#examineLambdaSpecifics: Type element for DefaultInterface should not be null", annotatedType);
		assertFalse("Java8ElementProcessor#examineLambdaSpecifics: Type DefaultInterface is not a functional interface", _elementUtils.isFunctionalInterface(annotatedType));

		method = null;
		members = _elementUtils.getAllMembers(annotatedType);
		for (ExecutableElement member : ElementFilter.methodsIn(members)) {
			if ("defaultMethod".equals(member.getSimpleName().toString())) {
				method = member;
				break;
			}
		}
		assertNotNull("Java8ElementProcessor#examineLambdaSpecifics: Element for method defaultMethod() should not be null", method);
		assertTrue("Java8ElementProcessor#examineLambdaSpecifics: Method defaultMethod() should be a default method", method.isDefault());
		modifiers = method.getModifiers();
		assertModifiers(modifiers, new String[]{"public", "default"});

		method = null;
		members = _elementUtils.getAllMembers(annotatedType);
		for (ExecutableElement member : ElementFilter.methodsIn(members)) {
			if ("anotherDefault".equals(member.getSimpleName().toString())) {
				method = member;
				break;
			}
		}
		assertNotNull("Java8ElementProcessor#examineLambdaSpecifics: Element for method anotherDefault() should not be null", method);
		assertTrue("Java8ElementProcessor#examineLambdaSpecifics: Method anotherDefault() should be a default method", method.isDefault());
		modifiers = method.getModifiers();
		assertModifiers(modifiers, new String[]{"public", "default"});
		
		
		method = null;
		for (ExecutableElement member : ElementFilter.methodsIn(members)) {
			if ("staticMethod".equals(member.getSimpleName().toString())) {
				method = member;
				break;
			}
		}
		assertNotNull("Java8ElementProcessor#examineLambdaSpecifics: Element for method staticMethod() should not be null", method);
		assertFalse("Java8ElementProcessor#examineLambdaSpecifics: Method staticMethod() shoule not be a default method", method.isDefault());
		modifiers = method.getModifiers();
		assertModifiers(modifiers, new String[]{"public", "static"});

		annotatedType = _elementUtils.getTypeElement("targets.model8.FunctionalInterface");
		assertNotNull("Java8ElementProcessor#examineLambdaSpecifics: Type element for FunctionalInterface should not be null", annotatedType);
		assertTrue("Java8ElementProcessor#examineLambdaSpecifics: Type FunctionalInterface should be a functional interface", _elementUtils.isFunctionalInterface(annotatedType));

		method = null;
		members = _elementUtils.getAllMembers(annotatedType);
		for (ExecutableElement member : ElementFilter.methodsIn(members)) {
			if ("abstractMethod".equals(member.getSimpleName().toString())) {
				method = member;
				break;
			}
		}
		assertNotNull("Java8ElementProcessor#examineLambdaSpecifics: Element for method abstractMethod() should not be null", method);
		assertFalse("Java8ElementProcessor#examineLambdaSpecifics: Method abstractMethod() should not be a default method", method.isDefault());
	}

	public void testSE8Specifics() {
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.X");
		examineSE8AnnotationMethods("Java8ElementProcessor#examineSE8Specifics: ", annotatedType, "c");

		List<? extends Element> members = _elementUtils.getAllMembers(annotatedType);
		ExecutableElement method = null;
		VariableElement field = null, field1 = null, field11 = null;
		ExecutableElement method2 = null;
		for (Element member : members) {
			if ("foo".equals(member.getSimpleName().toString())) {
				method = (ExecutableElement) member;
			} else if ("_field".equals(member.getSimpleName().toString())) {
				field = (VariableElement) member;
			} else if ("noAnnotationHere".equals(member.getSimpleName().toString())) {
				method2 = (ExecutableElement) member;
			} else if ("_field1".equals(member.getSimpleName().toString())) {
				field1 = (VariableElement) member;
			} else if ("_field11".equals(member.getSimpleName().toString())) {
				field11 = (VariableElement) member;
			}
			
		}
		assertNotNull("Method should not be null", method);
		TypeMirror typeMirror = method.getReturnType();
		assertNotNull("Java8ElementProcessor#examineSE8Specifics: Element for method foo should not be null", typeMirror);
		examineSE8AnnotationMethods("Java8ElementProcessor#examineSE8Specifics: ", typeMirror, "m");
		List<? extends AnnotationMirror> list = typeMirror.getAnnotationMirrors();
		assertEquals("Java8ElementProcessor#examineSE8Specifics: Incorrect no of annotation mirrors", 1, list.size());
		assertNotNull("Java8ElementProcessor#examineSE8Specifics: Element for field _field should not be null", field);
		typeMirror = field.asType(); 
		examineSE8AnnotationMethods("Java8ElementProcessor#examineSE8Specifics: ", typeMirror, "f");
		
		TypeMirror similar = typeMirror;
		typeMirror = field1.asType();
		assertFalse("Should be of same type", _typeUtils.isSameType(typeMirror, similar));
		verifyAnnotations(typeMirror, new String[]{"@Type(value=f1)"});
		similar = field11.asType();
		assertTrue("Should be of same type", _typeUtils.isSameType(typeMirror, similar));
		
		typeMirror = method2.getReturnType();
		assertNotNull("Java8ElementProcessor#examineSE8Specifics: Element for method noAnnotationHere should not be null", typeMirror);
		Type annot = typeMirror.getAnnotation(Type.class);
		assertNull("Annotation should not be present", annot);
		Type[] annots = typeMirror.getAnnotationsByType(Type.class);
		assertEquals("Annotation is not empty list", 0, annots.length);
	}
	
	public void testTypeAnnotations() {
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.X");
		TypeMirror superType = annotatedType.getSuperclass();
		assertNotNull("Java8ElementProcessor#examineSE8Specifics: super type not be null", superType);
		verifyAnnotations(superType, new String[]{"@Type(value=s)"});

		List<? extends TypeMirror> interfaces  = annotatedType.getInterfaces();
		assertNotNull("Java8ElementProcessor#examineSE8Specifics: super interfaces list should not be null", interfaces);
		assertEquals("Java8ElementProcessor#examineSE8Specifics: incorrect no of super interfaces", 2, interfaces.size());
		superType = interfaces.get(0);
		verifyAnnotations(superType, new String[]{"@Type(value=i1)"});
		superType = interfaces.get(1);
		verifyAnnotations(superType, new String[]{"@Type(value=i2)"});
	}
	
	public void testTypeAnnotations1() {
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.X");
		List<? extends Element> members = _elementUtils.getAllMembers(annotatedType);
		ExecutableElement method = null;
		for (Element member : members) {
			if ("bar".equals(member.getSimpleName().toString())) {
				method = (ExecutableElement) member;
			}
		}
		List<? extends VariableElement> params = method.getParameters();
		assertEquals("Incorrect no of params for method bar()", 2, params.size());
		VariableElement param = params.get(0);
		TypeMirror typeMirror = param.asType();
		verifyAnnotations(typeMirror, new String[]{"@Type(value=p1)"});
		param = params.get(1);
		typeMirror = param.asType();
		verifyAnnotations(typeMirror, new String[]{"@Type(value=p2)"});
	}
	
	public void testTypeAnnotations2() {
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.Y");
		List<? extends Element> members = _elementUtils.getAllMembers(annotatedType);
		VariableElement field2 = null;
		VariableElement field3 = null;
		for (Element member : members) {
			if ("_field2".equals(member.getSimpleName().toString())) {
				field2 = (VariableElement) member;
			} else if ("_field3".equals(member.getSimpleName().toString())) {
				field3 = (VariableElement) member;
			}
		}
		
		//@Type("f") String @Type("f1") [] @Type("f2") [] _field2 @Type("f3") [], _field3 @Type("f4") [][] = null;
		assertNotNull("Java8ElementProcessor#examineSE8Specifics: Element for field _field2 should not be null", field2);
		TypeMirror typeMirror = field2.asType();
		assertEquals("Should be an array type", TypeKind.ARRAY, typeMirror.getKind());
		verifyAnnotations(typeMirror, new String[]{"@Type(value=f3)"});
		typeMirror = ((ArrayType) typeMirror).getComponentType();
		assertEquals("Should be an array type", TypeKind.ARRAY, typeMirror.getKind());
		verifyAnnotations(typeMirror, new String[]{"@Type(value=f1)"});
		typeMirror = ((ArrayType) typeMirror).getComponentType();
		assertEquals("Should be an array type", TypeKind.ARRAY, typeMirror.getKind());
		verifyAnnotations(typeMirror, new String[]{"@Type(value=f2)"});

		assertNotNull("Java8ElementProcessor#examineSE8Specifics: Element for field _field3 should not be null", field3);
		typeMirror = field3.asType();
		// The second field binding doesn't seem to have the annotations. To be investigated
		verifyAnnotations(typeMirror, new String[]{"@Type(value=f4)"});
		typeMirror = ((ArrayType) typeMirror).getComponentType();
		assertEquals("Should be an array type", TypeKind.ARRAY, typeMirror.getKind());
		verifyAnnotations(typeMirror, new String[]{});
		typeMirror = ((ArrayType) typeMirror).getComponentType();
		assertEquals("Should be an array type", TypeKind.ARRAY, typeMirror.getKind());
		verifyAnnotations(typeMirror, new String[]{"@Type(value=f1)"});
		typeMirror = ((ArrayType) typeMirror).getComponentType();
		assertEquals("Should be an array type", TypeKind.ARRAY, typeMirror.getKind());
		verifyAnnotations(typeMirror, new String[]{"@Type(value=f2)"});
	}
	
	public void testTypeAnnotations3() {
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.Y");
		List<? extends Element> members = _elementUtils.getAllMembers(annotatedType);
		ExecutableElement method = null;
		for (Element member : members) {
			if ("foo".equals(member.getSimpleName().toString())) {
				method = (ExecutableElement) member;
			}
		}
		// @Type("m") String @Type("m1") [] foo() @Type("m2") [] @Type("m3") [] {}
		assertNotNull("Method should not be null", method);
		TypeMirror typeMirror = method.getReturnType();
		verifyAnnotations(typeMirror, new String[]{"@Type(value=m2)"});
		assertEquals("Should be an array type", TypeKind.ARRAY, typeMirror.getKind());
		typeMirror = ((ArrayType) typeMirror).getComponentType();
		verifyAnnotations(typeMirror, new String[]{"@Type(value=m3)"});
		assertEquals("Should be an array type", TypeKind.ARRAY, typeMirror.getKind());
		typeMirror = ((ArrayType) typeMirror).getComponentType();
		verifyAnnotations(typeMirror, new String[]{"@Type(value=m1)"});
		assertEquals("Should be an array type", TypeKind.ARRAY, typeMirror.getKind());
		typeMirror = ((ArrayType) typeMirror).getComponentType();
		verifyAnnotations(typeMirror, new String[]{"@Type(value=m)"});
	}

	public void testTypeAnnotations4() {
		// void bar( @Type("p1") String [] a @Type("p2") [], @Type("p3") int @Type("p4") [] b [] @Type("p5") []) {}
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.Y");
		List<? extends Element> members = _elementUtils.getAllMembers(annotatedType);
		ExecutableElement method = null;
		for (Element member : members) {
			if ("bar".equals(member.getSimpleName().toString())) {
				method = (ExecutableElement) member;
			}
		}
		assertNotNull("Method should not be null", method);
		List<? extends VariableElement> params = method.getParameters();
		assertEquals("Incorrect no of params for method bar()", 2, params.size());
		VariableElement param = params.get(0);
		TypeMirror typeMirror = param.asType();
		verifyAnnotations(typeMirror, new String[]{"@Type(value=p2)"});
		assertEquals("Should be an array type", TypeKind.ARRAY, typeMirror.getKind());
		typeMirror = ((ArrayType) typeMirror).getComponentType();
		
		verifyAnnotations(typeMirror, new String[]{});
		assertEquals("Should be an array type", TypeKind.ARRAY, typeMirror.getKind());
		typeMirror = ((ArrayType) typeMirror).getComponentType();
		verifyAnnotations(typeMirror, new String[]{"@Type(value=p1)"});

		param = params.get(1);
		typeMirror = param.asType();
		verifyAnnotations(typeMirror, new String[]{});
		assertEquals("Should be an array type", TypeKind.ARRAY, typeMirror.getKind());
		typeMirror = ((ArrayType) typeMirror).getComponentType();
		
		verifyAnnotations(typeMirror, new String[]{"@Type(value=p5)"});
		assertEquals("Should be an array type", TypeKind.ARRAY, typeMirror.getKind());
		typeMirror = ((ArrayType) typeMirror).getComponentType();
		verifyAnnotations(typeMirror, new String[]{"@Type(value=p4)"});
		assertEquals("Should be an array type", TypeKind.ARRAY, typeMirror.getKind());
		typeMirror = ((ArrayType) typeMirror).getComponentType();
		verifyAnnotations(typeMirror, new String[]{"@Type(value=p3)"});
		
	}
	
	public void testTypeAnnotations5() {
		// void foo2() throws (@Type("e1") NullPointerException, (@Type("e2") ArrayIndexOutOfBoundsException {}
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.Y");
		List<? extends Element> members = _elementUtils.getAllMembers(annotatedType);
		ExecutableElement method = null;
		for (Element member : members) {
			if ("foo2".equals(member.getSimpleName().toString())) {
				method = (ExecutableElement) member;
			}
		}
		List<?extends TypeMirror> exceptions = method.getThrownTypes();
		assertEquals("Incorrect no of thrown exceptions", 2, exceptions.size());
		TypeMirror typeMirror = exceptions.get(0);
		verifyAnnotations(typeMirror, new String[]{"@Type(value=e1)"});
		typeMirror = exceptions.get(1);
		verifyAnnotations(typeMirror, new String[]{"@Type(value=e2)"});
	}

	public void testTypeAnnotations6() {
		// void bar2 (@Type("p1") String @Type("p2") [] @Type("p3") ... args) {}
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.Y");
		List<? extends Element> members = _elementUtils.getAllMembers(annotatedType);
		ExecutableElement method = null;
		for (Element member : members) {
			if ("bar2".equals(member.getSimpleName().toString())) {
				method = (ExecutableElement) member;
			}
		}
		List<? extends VariableElement> params = method.getParameters();
		assertEquals("Incorrect no of parameters", 1, params.size());
		TypeMirror typeMirror = params.get(0).asType();
		verifyAnnotations(typeMirror, new String[]{"@Type(value=p2)"});
		assertEquals("Should be an array type", TypeKind.ARRAY, typeMirror.getKind());
		typeMirror = ((ArrayType) typeMirror).getComponentType();
		verifyAnnotations(typeMirror, new String[]{"@Type(value=p3)"});
		assertEquals("Should be an array type", TypeKind.ARRAY, typeMirror.getKind());
		typeMirror = ((ArrayType) typeMirror).getComponentType();
		verifyAnnotations(typeMirror, new String[]{"@Type(value=p1)"});

	}

	public void testTypeAnnotations7() {
		// public class Z <@Type("tp1") K, @Type("tp2") V> {
		TypeElement typeZ = _elementUtils.getTypeElement("targets.model8.Z");
		TypeMirror typeMirror = typeZ.asType();
		List<? extends TypeParameterElement> typeParams = typeZ.getTypeParameters();
		assertEquals("Incorrect no of type params", 2, typeParams.size());
		TypeParameterElement typeParam = typeParams.get(0);
		verifyAnnotations(typeParam, new String[]{"@Type(value=tp1)"});
		typeMirror = typeParam.asType();
		verifyAnnotations(typeMirror, new String[]{"@Type(value=tp1)"});
		typeParam = typeParams.get(1);
		typeMirror = typeParam.asType();
		verifyAnnotations(typeParam, new String[]{"@Type(value=tp2)"});
		verifyAnnotations(typeMirror, new String[]{"@Type(value=tp2)"});

		// public <T> Z(@Type T t){}
		List<? extends Element> members = _elementUtils.getAllMembers(typeZ);
		for (ExecutableElement method : ElementFilter.constructorsIn(members)) {
			ExecutableType executabletype = (ExecutableType) method.asType();
			List<? extends TypeMirror> list = executabletype.getParameterTypes();
			List<? extends VariableElement> list1 = method.getParameters();
			for(int i = 0; i < list1.size(); i++) {
				VariableElement variableelement = list1.get(i);
				if (method.getSimpleName().toString().equals("<init>")) {
					assertEquals("Trouble!", list.get(i), variableelement.asType());
				}
			}
		}
	}
	
	public void testTypeAnnotations8() {
		TypeElement typeZ = _elementUtils.getTypeElement("targets.model8.Z");
		List<? extends Element> members = _elementUtils.getAllMembers(typeZ);
		ExecutableElement method = null;
		VariableElement field = null;
		for (Element member : members) {
			if ("foo".equals(member.getSimpleName().toString())) {
				method = (ExecutableElement) member;
			} else if ("z1".equals(member.getSimpleName().toString())) {
				field = (VariableElement) member;
			}
		}
		
		// public <@Type("mp1") T, @Type("mp2") U> void foo() {}	
		List<? extends TypeParameterElement> typeParams = method.getTypeParameters();
		assertEquals("Incorrect no of type params", 2, typeParams.size());
		TypeParameterElement typeParam = typeParams.get(0);
		verifyAnnotations(typeParam, new String[]{"@Type(value=mp1)"});
		verifyAnnotations(typeParam.asType(), new String[]{"@Type(value=mp1)"});
		typeParam = typeParams.get(1);
		verifyAnnotations(typeParam, new String[]{"@Type(value=mp2)"});
		verifyAnnotations(typeParam.asType(), new String[]{"@Type(value=mp2)"});
		//Z<@Type("ta1") String, @Type("ta2") Object> z1 = null;
		// APIs don't expose the type arguments on a TypeMirror
		TypeMirror typeMirror = field.asType();
		verifyAnnotations(typeMirror, new String[]{});
	}

	public void testTypeAnnotations9() {
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.X");
		List<? extends Element> members = _elementUtils.getAllMembers(annotatedType);
		
		VariableElement field2 = null;
		for (VariableElement member : ElementFilter.fieldsIn(members)) {
			if ("_field2".equals(member.getSimpleName().toString())) {
				field2 = member;
				break;
			}
		}
		TypeMirror typeMirror = field2.asType();
		Type$1 annot1 = typeMirror.getAnnotation(Type$1.class);
		assertNotNull("Annotation should not be null", annot1);
		Type.One annot2 = typeMirror.getAnnotation(Type.One.class);
		assertNotNull("Annotation should not be null", annot2);
	}
	
	public void testTypeAnnotations10() {
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.X");
		List<? extends Element> members = _elementUtils.getAllMembers(annotatedType);
		VariableElement field3 = null;
		for (Element member : members) {
			if ("_field3".equals(member.getSimpleName().toString())) {
				field3 = (VariableElement) member;
			}
		}
		verifyAnnotations(annotatedType, new String[]{"@Type(value=c)"});
		verifyAnnotations(annotatedType.asType(), new String[]{});
		verifyAnnotations(field3, new String[]{});
		verifyAnnotations(field3.asType(), new String[]{});
	}

	public void testTypeAnnotations11() {
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.X");
		List<? extends Element> members = _elementUtils.getAllMembers(annotatedType);
		VariableElement xy = null;
		for (Element member : members) {
			if ("xy".equals(member.getSimpleName().toString())) {
				xy = (VariableElement) member;
			}
		}
		verifyAnnotations(xy, new String[]{});
		verifyAnnotations(xy.asType(), new String[]{"@Type(value=xy)"});
		
		Set<String> expectedElementNames = new HashSet<String>(ELEMENT_NAMES.length);
		for (String name : ELEMENT_NAMES) {
			expectedElementNames.add(name);
		}
		Set<? extends Element> actualElments = roundEnv.getElementsAnnotatedWith(Type.class);
		assertNotNull("RoundEnvironment#getElementsAnnotatedWith returned null", actualElments);
		
		for (Element e : actualElments) {
			if (e instanceof TypeElement) {
				String name = ((TypeElement) e).getQualifiedName().toString();
				if (!expectedElementNames.remove(name)) {
					reportError("Missing root element " + name);
				}
			} else if (e instanceof TypeParameterElement) {
				String name = ((TypeParameterElement) e).getSimpleName().toString();
				if (!expectedElementNames.remove(name)) {
					reportError("Missing root element " + name);
				}
			}
		}
		assertTrue("Found unexpected extra elements", expectedElementNames.isEmpty());
	}

	private void tTypeAnnotations12(TypeElement annotatedType) {
		List<? extends Element> members = _elementUtils.getAllMembers(annotatedType);
		ExecutableElement bar2 = null;
		ExecutableElement constr = null;
		ExecutableElement constr2 = null;
		for (Element member : members) {
			if ("bar2".equals(member.getSimpleName().toString())) {
				bar2 = (ExecutableElement) member;
			} else if ("<init>".equals(member.getSimpleName().toString())) {
				if (((ExecutableElement) member).getParameters().isEmpty()) {
					constr = (ExecutableElement) member;
				} else {
					constr2 = (ExecutableElement) member;
				}
			}
		}
		TypeMirror typeMirror = bar2.getReceiverType();
		verifyAnnotations(typeMirror, new String[]{"@Type(value=receiver)"});
		ExecutableType type = (ExecutableType) bar2.asType();
		verifyAnnotations(type.getReceiverType(), new String[]{"@Type(value=receiver)"});

		verifyAnnotations(constr, new String[]{});
		type = (ExecutableType) constr.asType();
		verifyAnnotations(type, new String[]{});

		verifyAnnotations(constr2, new String[]{"@Type1(value=constr2)"});
		type = (ExecutableType) constr2.asType();
		verifyAnnotations(type, new String[]{});
	}

	public void testTypeAnnotations12() {
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.X");
		tTypeAnnotations12(annotatedType);
	}

	public void testTypeAnnotations12Binary() {
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model9.X");
		tTypeAnnotations12(annotatedType);
	}
	
	public void testTypeAnnotations13() {
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.X");
		List<? extends Element> members = _elementUtils.getAllMembers(annotatedType);
		
		VariableElement field = null;
		for (VariableElement member : ElementFilter.fieldsIn(members)) {
			if ("_i".equals(member.getSimpleName().toString())) {
				field = member;
				break;
			}
		}
		TypeMirror typeMirror = field.asType();
		verifyAnnotations(typeMirror, new String[]{});
	}

	public void testTypeAnnotations14() {
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.X");
		List<? extends Element> members = _elementUtils.getAllMembers(annotatedType);
		ExecutableElement main = null;
		ExecutableElement constr = null;
		TypeElement XY = null;
		for (Element member : members) {
			if ("main".equals(member.getSimpleName().toString())) {
				main = (ExecutableElement) member;
			} else if ("<init>".equals(member.getSimpleName().toString())) {
				constr = (ExecutableElement) member;
			} else if ("XY".equals(member.getSimpleName().toString())) {
				XY = (TypeElement) member;
			}
		}
		TypeMirror typeMirror = main.getReceiverType();
		assertNotNull("TypeMirror should not be null", typeMirror);
		assertSame("Should be no type", TypeKind.NONE, typeMirror.getKind());
		ExecutableType type = (ExecutableType) main.asType();
		typeMirror = type.getReceiverType();
		assertNotNull("TypeMirror should not be null", typeMirror);
		assertSame("Should be no type", TypeKind.NONE, typeMirror.getKind());				
		typeMirror = constr.getReceiverType();
		assertNotNull("TypeMirror should not be null", typeMirror);
		assertSame("Should be no type", TypeKind.NONE, typeMirror.getKind());

		Type[] annotations = typeMirror.getAnnotationsByType(Type.class);
		assertEquals("Annotations arrays should be empty", 0, annotations.length);

		type = (ExecutableType) constr.asType();
		typeMirror = type.getReceiverType();
		assertNotNull("TypeMirror should not be null", typeMirror);
		assertSame("Should be no type", TypeKind.NONE, typeMirror.getKind());
		
		members = _elementUtils.getAllMembers(XY);
		for (Element member : members) {
			if ("<init>".equals(member.getSimpleName().toString())) {
				constr = (ExecutableElement) member;
			}
		}
		typeMirror = constr.getReceiverType();
		assertNotNull("TypeMirror should not be null", typeMirror);
		assertNotSame("Should not be no type", TypeKind.NONE, typeMirror.getKind());
		verifyAnnotations(typeMirror, new String[]{"@Type(value=receiver)"});
		type = (ExecutableType) constr.asType();
		typeMirror = type.getReceiverType();
		assertNotNull("TypeMirror should not be null", typeMirror);
		verifyAnnotations(typeMirror, new String[]{"@Type(value=receiver)"});
		assertNotSame("Should not be no type", TypeKind.NONE, typeMirror.getKind());
	}

	public void testTypeAnnotations15() {
		Set<String> expectedElementNames = new HashSet<String>(TYPE_PARAM_ELEMENTS_Z1.length);
		for (String name : TYPE_PARAM_ELEMENTS_Z1) {
			expectedElementNames.add(name);
		}
		Set<? extends Element> actualElments = roundEnv.getElementsAnnotatedWith(Type.class);
		assertNotNull("RoundEnvironment#getElementsAnnotatedWith returned null", actualElments);
		
		for (Element e : actualElments) {
			if (e instanceof TypeParameterElement) {
				String name = ((TypeParameterElement) e).getSimpleName().toString();
				if (!expectedElementNames.remove(name)) {
					reportError("Missing root element " + name);
				}
			}
		}
		assertTrue("Found unexpected extra elements", expectedElementNames.isEmpty());
	}

	public void testTypeAnnotations16() {
		Set<String> expectedElementNames = new HashSet<String>(TYPE_PARAM_ELEMENTS_Z2.length);
		for (String name : TYPE_PARAM_ELEMENTS_Z2) {
			expectedElementNames.add(name);
		}
		Set<? extends Element> actualElments = roundEnv.getElementsAnnotatedWith(Type.class);
		assertNotNull("RoundEnvironment#getElementsAnnotatedWith returned null", actualElments);
		
		for (Element e : actualElments) {
			if (e instanceof TypeParameterElement) {
				String name = ((TypeParameterElement) e).getSimpleName().toString();
				if (!expectedElementNames.remove(name)) {
					reportError("Missing root element " + name);
				}
			}
		}
		assertTrue("Found unexpected extra elements", expectedElementNames.isEmpty());
	}

	public void testRepeatedAnnotations17() {
		Set<? extends Element> actualElments = roundEnv.getElementsAnnotatedWith(Foo.class); // discovery is always in terms of container
		assertNotNull("RoundEnvironment#getElementsAnnotatedWith returned null", actualElments);
		assertTrue("Found unexpected elements", actualElments.size() == 0);
		
		actualElments = roundEnv.getElementsAnnotatedWith(FooContainer.class);
		assertNotNull("RoundEnvironment#getElementsAnnotatedWith returned null", actualElments);
		assertTrue("Found unexpected elements", actualElments.size() == 1);
		
		for (Element e : actualElments) {
			verifyAnnotations(e, new String[]{"@FooContainer(value=@org.eclipse.jdt.compiler.apt.tests.annotations.Foo,@org.eclipse.jdt.compiler.apt.tests.annotations.Foo)"},
					new String [] {"@FooContainer(value=[@org.eclipse.jdt.compiler.apt.tests.annotations.Foo, @org.eclipse.jdt.compiler.apt.tests.annotations.Foo])"});
			Annotation annot = e.getAnnotation(Foo.class);
			assertNull("Repeating annotation should not be seen through old API", annot);
			annot = e.getAnnotation(FooContainer.class);
			assertNotNull("Container missing", annot);
			Annotation [] annots = e.getAnnotationsByType(FooContainer.class);
			assertTrue("Should not be empty", annots.length == 1);
			annots = e.getAnnotationsByType(Foo.class);
			assertTrue("Should be 2", annots.length == 2);
			assertEquals("@Foo missing", "@org.eclipse.jdt.compiler.apt.tests.annotations.Foo()", "@org.eclipse.jdt.compiler.apt.tests.annotations.Foo",  annots[0].toString());
			assertEquals("@Foo missing", "@org.eclipse.jdt.compiler.apt.tests.annotations.Foo()", "@org.eclipse.jdt.compiler.apt.tests.annotations.Foo", annots[1].toString());
		}
	}
	
	public void testRepeatedAnnotations18() {
		Set<? extends Element> actualElments = roundEnv.getElementsAnnotatedWith(Foo.class); // discovery is always in terms of container
		assertNotNull("RoundEnvironment#getElementsAnnotatedWith returned null", actualElments);
		assertTrue("Found unexpected elements", actualElments.size() == 0);
		
		actualElments = roundEnv.getElementsAnnotatedWith(FooContainer.class);
		assertNotNull("RoundEnvironment#getElementsAnnotatedWith returned null", actualElments);
		assertTrue("Found unexpected elements", actualElments.size() == 1);
		
		for (Element e : actualElments) {
			verifyAnnotations(e, new String[]{"@FooContainer(value=@org.eclipse.jdt.compiler.apt.tests.annotations.Foo,@org.eclipse.jdt.compiler.apt.tests.annotations.Foo)"},
					new String [] {"@FooContainer(value=[@org.eclipse.jdt.compiler.apt.tests.annotations.Foo, @org.eclipse.jdt.compiler.apt.tests.annotations.Foo])"});
			Annotation annot = e.getAnnotation(Foo.class);
			assertNull("Repeating annotation should not be seen through old API", annot);
			annot = e.getAnnotation(FooContainer.class);
			assertNotNull("Container missing", annot);
			Annotation [] annots = e.getAnnotationsByType(FooContainer.class);
			assertTrue("Should not be empty", annots.length == 1);
			annots = e.getAnnotationsByType(Foo.class);
			assertTrue("Should be 2", annots.length == 2);
			assertEquals("@Foo missing", "@org.eclipse.jdt.compiler.apt.tests.annotations.Foo()", "@org.eclipse.jdt.compiler.apt.tests.annotations.Foo",  annots[0].toString());
			assertEquals("@Foo missing", "@org.eclipse.jdt.compiler.apt.tests.annotations.Foo()", "@org.eclipse.jdt.compiler.apt.tests.annotations.Foo", annots[1].toString());
		}
	}
	public void testRepeatedAnnotations19() { // Goo is wrapped by GooNonContainer, but Goo is not repeatable.
		Set<? extends Element> actualElments = roundEnv.getElementsAnnotatedWith(Goo.class); // discovery is always in terms of container
		assertNotNull("RoundEnvironment#getElementsAnnotatedWith returned null", actualElments);
		assertTrue("Found unexpected elements", actualElments.size() == 0);
		
		actualElments = roundEnv.getElementsAnnotatedWith(GooNonContainer.class);
		assertNotNull("RoundEnvironment#getElementsAnnotatedWith returned null", actualElments);
		assertTrue("Found unexpected elements", actualElments.size() == 1);
		
		for (Element e : actualElments) {
			verifyAnnotations(e, new String[]{"@GooNonContainer(value=@org.eclipse.jdt.compiler.apt.tests.annotations.Goo,@org.eclipse.jdt.compiler.apt.tests.annotations.Goo)"},
					new String [] {"@GooNonContainer(value=[@org.eclipse.jdt.compiler.apt.tests.annotations.Goo, @org.eclipse.jdt.compiler.apt.tests.annotations.Goo])"});
			Annotation annot = e.getAnnotation(Goo.class);
			assertNull("Repeating annotation should not be seen through old API", annot);
			annot = e.getAnnotation(GooNonContainer.class);
			assertNotNull("Container missing", annot);
			Annotation [] annots = e.getAnnotationsByType(GooNonContainer.class);
			assertTrue("Should not be empty", annots.length == 1);
			annots = e.getAnnotationsByType(Goo.class); // Goo should not be unwrapped from the container as Goo is not a repeatable annotation.
			assertTrue("Should be 0", annots.length == 0);
		}
	}
	public void testRepeatedAnnotations20() { // Both Foo and FooContainer occur.
		Set<? extends Element> actualElments = roundEnv.getElementsAnnotatedWith(Foo.class); // discovery is always in terms of container
		assertNotNull("RoundEnvironment#getElementsAnnotatedWith returned null", actualElments);
		assertTrue("Found unexpected elements", actualElments.size() == 1);
		
		actualElments = roundEnv.getElementsAnnotatedWith(FooContainer.class);
		assertNotNull("RoundEnvironment#getElementsAnnotatedWith returned null", actualElments);
		assertTrue("Found unexpected elements", actualElments.size() == 1);
		
		for (Element e : actualElments) {
			verifyAnnotations(e, new String[]{"@FooContainer(value=@org.eclipse.jdt.compiler.apt.tests.annotations.Foo)", "@Foo()"},
					new String [] {"@FooContainer(value=[@org.eclipse.jdt.compiler.apt.tests.annotations.Foo])","@org.eclipse.jdt.compiler.apt.tests.annotations.Foo"});
			Annotation annot = e.getAnnotation(Foo.class);
			assertNotNull("Foo is not wrapped, so should be seen with old API", annot);
			annot = e.getAnnotation(FooContainer.class);
			assertNotNull("Container missing", annot);
			Annotation [] annots = e.getAnnotationsByType(FooContainer.class);
			assertTrue("Should not be empty", annots.length == 1);
			annots = e.getAnnotationsByType(Foo.class);
			assertTrue("Should be 2", annots.length == 2);
		}
	}
	
	public void testRepeatedAnnotations21() { // Foo is wrapped by a non-declared container
		Set<? extends Element> actualElments = roundEnv.getElementsAnnotatedWith(Foo.class); // discovery is always in terms of container
		assertNotNull("RoundEnvironment#getElementsAnnotatedWith returned null", actualElments);
		assertTrue("Found unexpected elements", actualElments.size() == 0);
		
		actualElments = roundEnv.getElementsAnnotatedWith(FooNonContainer.class);
		assertNotNull("RoundEnvironment#getElementsAnnotatedWith returned null", actualElments);
		assertTrue("Found unexpected elements", actualElments.size() == 1);
		
		for (Element e : actualElments) {
			verifyAnnotations(e, new String[]{"@FooNonContainer(value=@org.eclipse.jdt.compiler.apt.tests.annotations.Foo,@org.eclipse.jdt.compiler.apt.tests.annotations.Foo)"},
					new String [] {"@FooNonContainer(value=[@org.eclipse.jdt.compiler.apt.tests.annotations.Foo, @org.eclipse.jdt.compiler.apt.tests.annotations.Foo])"});
			Annotation annot = e.getAnnotation(Foo.class);
			assertNull("Foo should not be seen with old API", annot);
			annot = e.getAnnotation(FooNonContainer.class);
			assertNotNull("Container missing", annot);
			Annotation [] annots = e.getAnnotationsByType(FooNonContainer.class);
			assertTrue("Should not be empty", annots.length == 1);
			annots = e.getAnnotationsByType(Foo.class);
			assertTrue("Should be 0", annots.length == 0);
		}
	}
	
	public void testRepeatedAnnotations22() { // Repeating type annotations
		Set<? extends Element> actualElments = roundEnv.getElementsAnnotatedWith(Foo.class); // discovery is always in terms of container
		assertNotNull("RoundEnvironment#getElementsAnnotatedWith returned null", actualElments);
		assertTrue("Found unexpected elements", actualElments.size() == 2);
		
		for (Element e : actualElments) {
			if (e instanceof VariableElement) {
				VariableElement field = (VariableElement) e;
				TypeMirror mirror = field.asType();
				verifyAnnotations(mirror, new String[]{"@TFooContainer(value=@org.eclipse.jdt.compiler.apt.tests.annotations.TFoo,@org.eclipse.jdt.compiler.apt.tests.annotations.TFoo)"},
					new String [] {"@TFooContainer(value=[@org.eclipse.jdt.compiler.apt.tests.annotations.TFoo, @org.eclipse.jdt.compiler.apt.tests.annotations.TFoo])"});
				Annotation annot = mirror.getAnnotation(TFoo.class);
				assertNull("TFoo should not be seen with old API", annot);
				annot = mirror.getAnnotation(TFooContainer.class);
				assertNotNull("Container missing", annot);
				Annotation [] annots = mirror.getAnnotationsByType(TFooContainer.class);
				assertTrue("Should not be empty", annots.length == 1);
				annots = mirror.getAnnotationsByType(TFoo.class);
				assertTrue("Should be 2", annots.length == 2);
			}
		}
	}
	
	public void testTypeAnnotations23() {
		Set<? extends Element> allElements = roundEnv.getRootElements();
		for (Element element : allElements) {
			List<? extends AnnotationMirror> list = _elementUtils.getAllAnnotationMirrors(element);
			List<? extends AnnotationMirror> list1 = element.getAnnotationMirrors();
			assertTrue("Annotations mirrors returned by getAllAnnotationMirrors() must contain directly declared annotation mirrors", list.containsAll(list1));
		}
	}
	
	public void testRepeatedAnnotations24() {
		Set<? extends Element> actualElments = roundEnv.getElementsAnnotatedWith(IFoo.class); // discovery is always in terms of container
		assertNotNull("RoundEnvironment#getElementsAnnotatedWith returned null", actualElments);
		assertTrue("Found unexpected elements", actualElments.size() == 3);		
		for (Element e : actualElments) {
			if ("SubClass2".equals(e.getSimpleName().toString())) {
				IFoo annotation = e.getAnnotation(IFoo.class);
				assertTrue("Wrong annotation", annotation.value() == 5);
				IFooContainer container = e.getAnnotation(IFooContainer.class);
				assertTrue("Wrong annotation", container.value()[0].value() == 2);
				IFoo [] annotations = e.getAnnotationsByType(IFoo.class);
				assertTrue("Wrong count", annotations.length == 1);
				assertTrue("Wrong annotation", annotations[0].value() == 5);
				IFooContainer [] containers = e.getAnnotationsByType(IFooContainer.class);
				assertTrue("Wrong count", containers.length == 1);
				assertTrue("Wrong annotation", containers[0].value()[0].value() == 2);
			} else if ("SubClass".equals(e.getSimpleName().toString())) {
				IFoo annotation = e.getAnnotation(IFoo.class);
				assertTrue("Wrong annotation", annotation.value() == 1);
				IFooContainer container = e.getAnnotation(IFooContainer.class);
				assertTrue("Messed up", container.value().length == 2);
				assertTrue("Wrong annotation", container.value()[0].value() == 3);
				assertTrue("Wrong annotation", container.value()[1].value() == 4);
				IFoo [] annotations = e.getAnnotationsByType(IFoo.class);
				assertTrue("Wrong count", annotations.length == 2);
				assertTrue("Wrong annotation", annotations[0].value() == 3);
				assertTrue("Wrong annotation", annotations[1].value() == 4);
				IFooContainer [] containers = e.getAnnotationsByType(IFooContainer.class);
				assertTrue("Wrong count", containers.length == 1);
				assertTrue("Wrong annotation", containers[0].value()[0].value() == 3);
				assertTrue("Wrong annotation", containers[0].value()[1].value() == 4);
			} else if ("JEP120_6".equals(e.getSimpleName().toString())) {
				IFoo annotation = e.getAnnotation(IFoo.class);
				assertTrue("Wrong annotation", annotation.value() == 1);
				IFooContainer container = e.getAnnotation(IFooContainer.class);
				assertTrue("Messed up", container.value().length == 1);
				assertTrue("Wrong annotation", container.value()[0].value() == 2);
				IFoo [] annotations = e.getAnnotationsByType(IFoo.class);
				assertTrue("Wrong count", annotations.length == 2);
				assertTrue("Wrong annotation", annotations[0].value() == 1);
				assertTrue("Wrong annotation", annotations[1].value() == 2);
				IFooContainer [] containers = e.getAnnotationsByType(IFooContainer.class);
				assertTrue("Wrong count", containers.length == 1);
				assertTrue("Wrong annotation", containers[0].value()[0].value() == 2);
			}
		}
	}
	public void testRepeatedAnnotations25() {
		Set<? extends Element> actualElments = roundEnv.getElementsAnnotatedWith(IFooContainer.class); // discovery is always in terms of container
		assertNotNull("RoundEnvironment#getElementsAnnotatedWith returned null", actualElments);
		assertTrue("Found unexpected elements", actualElments.size() == 2);
		IFooContainer annotationOnSubclass = null, annotationOnJep7 = null;
		for (Element e : actualElments) {
			if ("SubClass3".equals(e.getSimpleName().toString())) {
				annotationOnSubclass = e.getAnnotation(IFooContainer.class);
			} else if ("JEP120_7".equals(e.getSimpleName().toString())) {
				annotationOnJep7 = e.getAnnotation(IFooContainer.class);
			}
		}
		assertTrue("Should be equals", annotationOnJep7.equals(annotationOnSubclass));
	}
	
	public void testTypeAnnotations26() {
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.Iface");
		List<? extends Element> members = _elementUtils.getAllMembers(annotatedType);
		ExecutableElement method = null;
		for (Element member : members) {
			if ("foo".equals(member.getSimpleName().toString())) {
				method = (ExecutableElement) member;
				
				List<? extends VariableElement> list = method.getParameters();
				VariableElement param = list.get(0);
				verifyAnnotations(param, new String[]{});
			}
		}
	}
	
	public void testTypeAnnotations27() {
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.model8.a.Test");
		List<? extends Element> members = _elementUtils.getAllMembers(annotatedType);
		for (Element member : members) {
			if ("foo".equals(member.getSimpleName().toString())) {
				ExecutableElement method = (ExecutableElement) member;
				
				List<? extends TypeParameterElement> list = method.getTypeParameters();
				TypeParameterElement tParam = list.get(0);
				verifyAnnotations(tParam, new String[]{"@MarkerContainer(value=[@targets.model8.a.Marker, @targets.model8.a.Marker])"});
			}
		}
		
	}
	// Disabled for now. Javac includes the CLASS element of the package-info in the root element if there's one.
	// But ECJ includes the Package element.
	public void testPackageAnnotations() {
		if ( roundNo++ == 0) {
			this.reportSuccessAlready = false;
			try {
				createPackageBinary();
			} catch (IOException e) {
				e.printStackTrace();
			}
			System.setProperty(this.getClass().getName(), "Processor did not fully do the job");
		} else {
			this.reportSuccessAlready = true;
			PackageElement packageEl = null;
			for (Element element : roundEnv.getRootElements()) {
				if (element.getKind() == ElementKind.PACKAGE) {
					packageEl = (PackageElement) element;
				} else {
					System.out.println(element);
				}
			}
			assertNotNull("Package element should not be null", packageEl);
			assertEquals("Incorrect package name", simpleName, packageEl.getSimpleName().toString());
			assertEquals("Incorrect package name", packageName, packageEl.getQualifiedName().toString());
			assertFalse("Package should not be unnamed", packageEl.isUnnamed()); 
		}
	}
	public void testBug520540() {
		PackageElement packageElement = _elementUtils.getPackageElement("targets.bug520540");
		assertNotNull("package element should not be null", packageElement);
		List<? extends Element> enclosedElements = packageElement.getEnclosedElements();
		assertEquals("Incorrect no of elements", 5, enclosedElements.size());
		List<String> typeElements = new ArrayList<>();
		for (Element element : enclosedElements) {
			if (element instanceof TypeElement) {
				typeElements.add(((TypeElement) element).getQualifiedName().toString());
			}
		}
		String[] types = new String[] { "targets.bug520540.GenericType", "targets.bug520540.MyEnum",
				"targets.bug520540.TypeEx", "targets.bug520540.TypeA", "targets.bug520540.AnnotB" };
		for (String string : types) {
			typeElements.remove(string);
		}
		assertEquals("found incorrect types", 0, typeElements.size());
	}
	public void testBug526288() {
		PackageElement packageElement = _elementUtils.getPackageElement("targets.testBug526288");
		assertNotNull("package element should not be null", packageElement);
		assertNull("package should have no enclosing element", packageElement.getEnclosingElement());
	}
	public void testEnumConstArguments() {
		TypeElement annotatedType = _elementUtils.getTypeElement("targets.bug521812.MyEnum");
		List<? extends Element> enclosedElements = annotatedType.getEnclosedElements();
		ExecutableElement constr = null;
		for (Element element : enclosedElements) {
			if (element.getSimpleName().toString().equals("<init>")) {
				constr = (ExecutableElement) element;
			}
		}
		assertNotNull("constructor should not be null", constr);
		List<? extends VariableElement> parameters = constr.getParameters();
		ExecutableType asType = (ExecutableType) constr.asType();
		List<? extends TypeMirror> parameterTypes = asType.getParameterTypes();
		assertEquals("param count and param type count should be same", parameters.size(), parameterTypes.size());
		for(int i = 0; i < parameters.size(); i++) {
			VariableElement param = parameters.get(i);
			TypeMirror asType2 = param.asType();
			assertEquals("Parameter type should be same", param.asType(), asType2);
		}
	}
	public void testBug531717() {
		NoType noType = _typeUtils.getNoType(TypeKind.NONE);
		TypeMirror erasure = _typeUtils.erasure(noType);
		assertSame("NoType should be same", noType, erasure);
		NullType nullType = _typeUtils.getNullType();
		erasure = _typeUtils.erasure(nullType);
		assertSame("NoType should be same", nullType, erasure);
	}
	private void createPackageBinary() throws IOException {
		String path = packageName.replace('.', '/');
		ClassLoader loader = getClass().getClassLoader();
		InputStream in = loader.getResourceAsStream(path + "/package-info.class");
		try {
			Filer filer = processingEnv.getFiler();
			OutputStream out = filer.createClassFile(packageName + ".package-info").openOutputStream();
			try {
				if (in != null && out != null) {
					int c = in.read();
					while (c != -1) {
						out.write(c);
						c = in.read();
					}
				}
			} finally {
				out.close();
			}
		} finally {
			in.close();
		}
	}	
	
	private String getExceptionStackTrace(Throwable t) {
		StringBuffer buf = new StringBuffer(t.getMessage());
		StackTraceElement[] traces = t.getStackTrace();
		for (int i = 0; i < traces.length; i++) {
			StackTraceElement trace = traces[i];
			buf.append("\n\tat " + trace);
			if (i == 12)
				break; // Don't dump all stacks
		}
		return buf.toString();
	}

	private void verifyAnnotations(AnnotatedConstruct construct, String[] annots) {
		List<? extends AnnotationMirror> annotations = construct.getAnnotationMirrors();
		assertEquals("Incorrect no of annotations", annots.length, annotations.size());
		for(int i = 0, length = annots.length; i < length; i++) {
			AnnotationMirror mirror = annotations.get(i);
			assertEquals("Invalid annotation value", annots[i], getAnnotationString(mirror));
		}
	}
	
	private void verifyAnnotations(AnnotatedConstruct construct, String[] annots, String [] alternateAnnots) {
		List<? extends AnnotationMirror> annotations = construct.getAnnotationMirrors();
		assertEquals("Incorrect no of annotations", annots.length, annotations.size());
		for(int i = 0, length = annots.length; i < length; i++) {
			AnnotationMirror mirror = annotations.get(i);
			assertEquals("Invalid annotation value", annots[i], alternateAnnots[i], getAnnotationString(mirror));
		}
	}

	private String getAnnotationString(AnnotationMirror annot) {
		DeclaredType annotType = annot.getAnnotationType();
		TypeElement type = (TypeElement) annotType.asElement();
		StringBuffer buf = new StringBuffer("@" + type.getSimpleName());
		Map<? extends ExecutableElement, ? extends AnnotationValue> values = annot.getElementValues();
		Set<? extends ExecutableElement> keys = values.keySet();
		buf.append('(');
		for (ExecutableElement executableElement : keys) { // @Marker3()
			buf.append(executableElement.getSimpleName());
			buf.append('=');
			AnnotationValue value = values.get(executableElement);
			buf.append(value.getValue());
		}
		buf.append(')');
		return buf.toString();
	}

	private <A extends Annotation> void examineSE8AnnotationMethods(String msg, AnnotatedConstruct construct,  String value) {
		Type annot = construct.getAnnotation(Type.class);
		assertNotNull(msg + "Annotation for element " + construct.toString() + " should not be null", annot);
		assertSame(msg + "Invalid annotation type" , Type.class, annot.annotationType());
		assertEquals(msg + "Invalid annotation value", value, annot.value());
		
		Type[] annots = construct.getAnnotationsByType(Type.class);
		assertEquals(msg + "Incorrect no of annotations", 1, annots.length);
		annot = annots[0];
		assertSame(msg + "Invalid annotation type" , Type.class, annots[0].annotationType());
		assertEquals(msg + "Invalid annotation value", value, annot.value());
	}
	
	@Override
	public void reportError(String msg) {
		throw new AssertionFailedError(msg);
	}
	
	public void assertModifiers(Set<Modifier> modifiers, String[] expected) {
		assertEquals("Incorrect no of modifiers", modifiers.size(), expected.length);
		Set<String> actual = new HashSet<String>(expected.length);
		for (Modifier modifier : modifiers) {
			actual.add(modifier.toString());
		}
		for(int i = 0, length = expected.length; i < length; i++) {
			boolean result = actual.remove(expected[i]);
			if (!result) reportError("Modifier not present :" + expected[i]);
		}
		if (!actual.isEmpty()) {
			reportError("Unexpected modifiers present:" + actual.toString());
		}
	}
	public void assertTrue(String msg, boolean value) {
		if (!value) reportError(msg);
	}
	public void assertFalse(String msg, boolean value) {
		if (value) reportError(msg);
	}
	public void assertSame(String msg, Object obj1, Object obj2) {
		if (obj1 != obj2) {
			reportError(msg + ", should be " + obj1.toString() + " but " + obj2.toString());
		}
	}
	public void assertNotSame(String msg, Object obj1, Object obj2) {
		if (obj1 == obj2) {
			reportError(msg + ", " + obj1.toString() + " should not be same as " + obj2.toString());
		}
	}
	public void assertNotNull(String msg, Object obj) {
		if (obj == null) {
			reportError(msg);
		}
	}
	public void assertNull(String msg, Object obj) {
		if (obj != null) {
			reportError(msg);
		}
	}
    public void assertEquals(String message, Object expected, Object actual) {
        if (equalsRegardingNull(expected, actual)) {
            return;
        } else {
        	reportError(message + ", expected " + expected.toString() + " but was " + actual.toString());
        }
    }

    public void assertEquals(String message, Object expected, Object alternateExpected, Object actual) {
        if (equalsRegardingNull(expected, actual) || equalsRegardingNull(alternateExpected, actual)) {
            return;
        } else {
        	reportError(message + ", expected " + expected.toString() + " but was " + actual.toString());
        }
    }
    
    static boolean equalsRegardingNull(Object expected, Object actual) {
        if (expected == null) {
            return actual == null;
        }
        return expected.equals(actual);
    }
    
	public void assertEquals(String msg, int expected, int actual) {
		if (expected != actual) {
			StringBuffer buf = new StringBuffer();
			buf.append(msg);
			buf.append(", expected " + expected + " but was " + actual);
			reportError(buf.toString());
		}
	}
	public void assertEquals(Object expected, Object actual) {
		if (expected != actual) {
			
		}
	}
	private class AssertionFailedError extends Error {
		private static final long serialVersionUID = 1L;

		public AssertionFailedError(String msg) {
			super(msg);
		}
	}
}
