package basics.utl;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import basics.testing.Test;

public class ClassUtl
{
@SuppressWarnings("unchecked")
Class c;

@SuppressWarnings("unchecked")
public ClassUtl(Class c)
{
   this.c = c;
}

@SuppressWarnings("unchecked")
public static String getPackage(Class clazz)
{
   String path = clazz.getName();
   int x = path.lastIndexOf(".");
   return x == -1 ? path : path.substring(0, x);
}

@SuppressWarnings("unchecked")
public String getPackage()
{
   return getPackage(c);
}

public ArrayList<String> getMethodNames(boolean all)
{
   Method [] theMethods = all ? c.getMethods() : c.getDeclaredMethods();
   ArrayList<String> names = new ArrayList<String>();
   for(int i = 0; i < theMethods.length; i++)
   {
      names.add(theMethods[i].getName());
   }
   return names;
}

public Method getMethod(String methodName)
{
   Method [] theMethods = c.getMethods();
   for(Method m : theMethods)
   {
      if(m.getName().equals(methodName))
         return m;
   }
   return null;
}

public ArrayList<String> getGetterMethodNames(boolean all)
{
   Method [] theMethods = all ? c.getMethods() : c.getDeclaredMethods();
   ArrayList<String> names = new ArrayList<String>();
   for(int i = 0; i < theMethods.length; i++)
   {
      if(theMethods[i].getName().startsWith("get")
         && !theMethods[i].getReturnType().getName().equals("void"))
      {
         names.add(theMethods[i].getName());
      }
   }
   return names;
}

public ArrayList<String> getSetterMethodNames(boolean all)
{
   Method [] theMethods = all ? c.getMethods() : c.getDeclaredMethods();
   ArrayList<String> names = new ArrayList<String>();
   for(int i = 0; i < theMethods.length; i++)
   {
      if(theMethods[i].getName().startsWith("set")
         && theMethods[i].getReturnType().getName().equals("void"))
      {
         names.add(theMethods[i].getName());
      }
   }
   return names;
}

public String getReturnType(String methodName)
{
   Method [] theMethods = c.getMethods();
   for(int i = 0; i < theMethods.length; i++)
   {
      if(methodName.equals(theMethods[i].getName()))
      {
         return theMethods[i].getReturnType().getName();
      }
   }
   return null;
}

public String getReturnTypeIgnoreCase(String methodName)
{
   Method [] theMethods = c.getMethods();
   for(int i = 0; i < theMethods.length; i++)
   {
      // Log.debug("METHOD " + theMethods[i].getName());
      if(methodName.equalsIgnoreCase(theMethods[i].getName()))
      {
         return theMethods[i].getReturnType().getName();
      }
   }
   return null;
}

public String [] getPublicFieldNamesArray()
{
   Field [] publicFields = c.getFields();
   String [] fields = new String [publicFields.length];
   for(int i = 0; i < publicFields.length; i++)
   {
      fields[i] = publicFields[i].getName();
   }
   return fields;
}

public List<String> getPublicFieldNames()
{
   Field [] publicFields = c.getFields();
   List<String> names = new ArrayList<String>();
   for(int i = 0; i < publicFields.length; i++)
   {
      names.add(publicFields[i].getName());
   }
   return names;
}

@SuppressWarnings("unchecked")
public String getFieldType(String field)
{
   Field [] publicFields = c.getFields();
   for(int i = 0; i < publicFields.length; i++)
   {
      if(publicFields[i].getName().equals(field))
      {
         Class typeClass = publicFields[i].getType();
         return typeClass.getName();
      }
   }
   return null;
}

//--------------------- testing -------------------------//
// boolean       Z
// byte          B
// char          C
// class or interface Lclassname
// double        D
// float         F
// int           I
// long          J
// short         S
private static class ClassUtlTestClass
{
public String  id;
public int     ndx;
public double  d;
public boolean wahr;

public void setWahr(boolean b)
{
}

public boolean getWahr()
{
   return wahr;
}
}

public static void unittest()
{
   ClassUtl cu = new ClassUtl(ClassUtlTestClass.class);
   Test.assertEqualsTrue(cu.getPackage(), "basics.utl", "wrong package? " + cu.getPackage());
   Test.assertEqualsTrue(cu.getFieldType("id"), "java.lang.String", "id is a string not "
      + cu.getFieldType("id"));
   Test.assertEqualsTrue(cu.getFieldType("ndx"), "int", "ndx is a int not "
      + cu.getFieldType("ndx"));
   Test.assertEqualsTrue(cu.getFieldType("d"), "double", "d is a double not "
      + cu.getFieldType("d"));
   Test.assertEqualsTrue(cu.getFieldType("wahr"), "boolean", "wahr is a boolean not "
      + cu.getFieldType("wahr"));
   List<String> names = cu.getMethodNames(true);
   Test.assertTrue(names.size() == 11, "11 methods expected not " + names.size());
   names = cu.getMethodNames(false);
   Test.assertTrue(names.size() == 2, "2 methods expected not " + names.size());
   Test.assertTrue(cu.getGetterMethodNames(false).size() == 1, "1 getter methods expected not "
      + cu.getGetterMethodNames(false).size());
   Test.assertTrue(cu.getSetterMethodNames(false).size() == 1, "1 setter methods expected");
}
}
