import java.lang.reflect.Field;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import librerias.implementacionesDeModelos.GrupoDeAL;

public class Test04
{
	public static boolean test() throws Throwable
	{
		final GrupoDeAL<Numero> grupoDe = new GrupoDeAL<Numero>();
		final Numero numero = new Numero(7);
		final boolean anyade = Test04.anyade(grupoDe, numero);
		if (!anyade)
			return false;
		final boolean eliminar = Test04.eliminar(grupoDe, numero);
		if (eliminar)
			return true;

		final GrupoDeAL<Numero> grupoDe2 = new GrupoDeAL<Numero>();
		final boolean anyade2 = Test04.anyade(grupoDe2, numero);
		final boolean eliminar2 = Test04.eliminar2(grupoDe2, numero);
		if (!anyade2 || !eliminar2)
			return false;

		return true;
	}
	private static boolean anyade(GrupoDeAL<Numero> grupoDe, Numero numero)
	{
		if (grupoDe.talla() != 0)
			return false;
		grupoDe.anyade(numero);
		if (grupoDe.talla() != 1)
			return false;
		grupoDe.anyade(numero);
		if (grupoDe.talla() != 2)
			return false;
		return true;
	}
	private static boolean eliminar(GrupoDeAL<Numero> grupoDe, Numero numero)
	{
		try
		{
			grupoDe.elimina(numero);
			if (grupoDe.talla() != 1)
				return false;
			grupoDe.elimina(numero);
			if (grupoDe.talla() != 0)
				return false;
		}
		catch (Throwable e)
		{
			return false;
		}
		return true;
	}
	private static boolean eliminar2(GrupoDeAL<Numero> grupoDe, Numero numero)
	{
		try
		{
			final ArrayList<Numero> elArray = Test04.getArrayList(grupoDe);

			elArray.remove(numero);
			if (grupoDe.talla() != 1)
				return false;
			elArray.remove(numero);
			if (grupoDe.talla() != 0)
				return false;
		}
		catch (Throwable e)
		{
			return false;
		}
		return true;
	}

	private static ArrayList<Numero> getArrayList(GrupoDeAL<Numero> grupoDe) throws Throwable
	{
		final List<Field> fieldsExcluded = new LinkedList<Field>();
		final Field[] fields = GrupoDeAL.class.getDeclaredFields();

		while (fieldsExcluded.size() < fields.length)
		{
			final Field field = Test04.getField(fields, "java.util.ArrayList", fieldsExcluded);
			final Class<?> fieldType = field.getType();
			final TypeVariable<?>[] typeParameters = fieldType.getTypeParameters();

			if (typeParameters.length == 1)
			{
				if (field == null)
					continue;

				field.setAccessible(true);
				return (ArrayList<Numero>) field.get(grupoDe);
			}
			fieldsExcluded.add(field);
		}

		if (((Object) grupoDe) instanceof ArrayList)
			return (ArrayList) (Object) grupoDe;

		return null;
	}
	private static Field getField(Class<?> clazz, String typeName, List<Field> fieldsExcluded)
	{
		final Field[] fields = GrupoDeAL.class.getDeclaredFields();

		return Test04.getField(fields, typeName, fieldsExcluded);
	}
	private static Field getField(Field[] fields, String typeName, List<Field> fieldsExcluded)
	{
		for (Field field : fields)
		{
			if (fieldsExcluded.contains(field))
				continue;

			final Class<?> fieldType = field.getType();
			final String fieldTypeName = fieldType.getName();

			if (fieldTypeName.equals(typeName))
				return field;
		}

		return null;
	}

	static class Numero
	{
		private int numero;

		public Numero(int numero)
		{
			this.numero = numero;
		}

		public int getNumero()
		{
			return this.numero;
		}

		public String toString()
		{
			return "Numero " + this.numero;
		}
	}
}