package code.validation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import org.junit.Assert;
import org.junit.Test;

public class CollectionSafeTest {

	private static final Class<CollectionUnsafeClass> UNSAFE_CLASS = CollectionUnsafeClass.class;
	private static final Class<CollectionSafeClass> SAFE_CLASS = CollectionSafeClass.class;

	@Test
	public void testSafeClassForEquals() throws Exception {
		Class<CollectionSafeClass> klass = SAFE_CLASS;

		checkEqualsMethod(klass);
	}

	@Test
	public void testSafeClassForHashCode() throws Exception {
		Class<CollectionSafeClass> klass = SAFE_CLASS;

		checkHashCodeMethod(klass);
	}

	@Test
	public void testUnsafeClassForEquals() throws Exception {
		Class<CollectionUnsafeClass> klass = UNSAFE_CLASS;

		checkEqualsMethod(klass);
	}

	@Test
	public void testUnsafeClassForHashCode() throws Exception {
		Class<CollectionUnsafeClass> klass = UNSAFE_CLASS;

		checkHashCodeMethod(klass);
	}

	private void checkEqualsMethod(Class<?> klass) {
		String methodName = "equals";
		Class<?> methodParameters[] = { Object.class };

		Class<?> providerClass = checkClass(klass, methodName, methodParameters);
		Assert.assertEquals(klass, providerClass);
	}

	private void checkHashCodeMethod(Class<?> klass) {
		String methodName = "hashCode";
		Class<?> methodParameters[] = {};

		Class<?> providerClass = checkClass(klass, methodName, methodParameters);
		Assert.assertEquals(klass, providerClass);
	}

	private Class<?> checkClass(Class<?> klass, String methodName, Class<?>[] parameters) {
		Annotation annotation = klass.getAnnotation(CollectionSafe.class);
		if (annotation instanceof CollectionSafe) {
			return checkMethod(klass, methodName, parameters);
		} else {
			throw new RuntimeException("No annotation in class " + klass);
		}
	}

	private Class<?> checkMethod(Class<?> klass, String methodName,
			Class<?>[] parameters) {
		try {
			Method method = klass.getMethod(methodName, parameters);
			return method.getDeclaringClass();
		} catch (NoSuchMethodException e) {
			throw new RuntimeException("No method '" + methodName + "' in class " + klass);
		} catch (SecurityException e) {
			throw new RuntimeException("SecurityException", e);
		}
	}
}

@@ -272,16 +272,17 @@
 .class;%0A
+%0A
 %09private
@@ -479,35 +479,105 @@
 ASS;%0A%0A%09%09
-checkEqualsMethod(k
+Class%3C?%3E providerClass = checkEqualsMethod(klass);%0A%09%09Assert.assertEquals(klass, providerC
 lass);%0A%09
@@ -697,37 +697,107 @@
 ASS;%0A%0A%09%09
-checkHashCodeMethod(k
+Class%3C?%3E providerClass = checkHashCodeMethod(klass);%0A%09%09Assert.assertEquals(klass, providerC
 lass);%0A%09
@@ -921,39 +921,115 @@
 ASS;%0A%0A%09%09
-checkEqualsMethod(klass
+Class%3C?%3E providerClass = checkEqualsMethod(klass);%0A%09%09Assert.assertFalse(klass.equals(providerClass)
 );%0A%09%7D%0A%0A%09
@@ -1151,16 +1151,41 @@
 ASS;%0A%0A%09%09
+Class%3C?%3E providerClass = 
 checkHas
@@ -1200,24 +1200,75 @@
 hod(klass);%0A
+%09%09Assert.assertFalse(klass.equals(providerClass));%0A
 %09%7D%0A%0A%09private
@@ -1264,28 +1264,32 @@
 %7D%0A%0A%09private 
-void
+Class%3C?%3E
  checkEquals
@@ -1402,32 +1402,14 @@
 %0A%0A%09%09
-Class%3C?%3E providerClass =
+return
  che
@@ -1458,53 +1458,8 @@
 s);%0A
-%09%09Assert.assertEquals(klass, providerClass);%0A
 %09%7D%0A%0A
@@ -1467,20 +1467,24 @@
 private 
-void
+Class%3C?%3E
  checkHa
@@ -1591,32 +1591,14 @@
 %0A%0A%09%09
-Class%3C?%3E providerClass =
+return
  che
@@ -1647,53 +1647,8 @@
 s);%0A
-%09%09Assert.assertEquals(klass, providerClass);%0A
 %09%7D%0A%0A
@@ -1908,17 +1908,19 @@
 rs);%0A%09%09%7D
- 
+%0A%09%09
 else %7B%0A%09
@@ -2056,20 +2056,17 @@
 hodName,
-%0A%09%09%09
+ 
 Class%3C?%3E

Fix tests