package cutils.reflection;

import java.lang.reflect.Method;
import java.util.Vector;


public class MethodList {
  private java.util.Vector v = new java.util.Vector();

  public MethodList(Class c) {
    java.lang.reflect.Method ma[] = c.getMethods();
    for (int i = 0; i < ma.length; i++)
      if (ma[i].getDeclaringClass() != Object.class)
        v.addElement(ma[i]);
  }

  public MethodList() {
  }
   public static Method[] getPrimMethods(MethodList ml) {
        Method m[] = ml.getWriteMethods();
        Vector v = new Vector();
        for (int i=0; i < m.length; i++){
             Method m1 = m[i];
            if(isAcceptableParamList(m1))
                v.addElement(m1);
        }
        Method newArray[] = new Method[v.size()];
        v.copyInto(newArray);
        return newArray;
    }

  public int index(java.lang.reflect.Method m1) {
    for (int i = 0; i < v.size(); i++) {
      java.lang.reflect.Method m2 = elementAt(i);
      if (equals(m1, m2))
        return i;
    }
    return -1;
  }
   public static boolean isAcceptableParamList(Method m){
       Class c[] =  m.getParameterTypes();
        for (int i=0; i < c.length; i++) {
            if ((! c[i].isPrimitive()) &&
                    (! c[i].equals(String.class))) return false;
        }
      return true;
    }

  java.lang.reflect.Method[] getMethodsWithNArgs(int n) {
    java.lang.reflect.Method m[] = getMethods();
    MethodList ml = new MethodList();
    for (int i = 0; i < m.length; i++) {
      Class ca[] = m[i].getParameterTypes();
      if (ca.length == n)
        ml.add(m[i]);
    }
    return ml.getMethods();
  }

  public java.lang.reflect.Method[] getWriteMethods() {
    java.lang.reflect.Method m[] = getMethods();
    MethodList ml = new MethodList();
    for (int i = 0; i < m.length; i++) {
      String s = m[i].getName();
      if (s.startsWith("set"))
        ml.add(m[i]);
    }
    return ml.getMethods();
  }

  public java.lang.reflect.Method[] getReadMethods() {
    java.lang.reflect.Method m[] = getMethods();
    MethodList ml = new MethodList();
    for (int i = 0; i < m.length; i++) {
      String s = m[i].getName();
      if (s.startsWith("get") || s.startsWith("is"))
        ml.add(m[i]);
    }
    return ml.getMethods();
  }

  public boolean containedBy(java.lang.reflect.Method m) {
    if (index(m) == -1) return false;
    return true;
  }

  /**
   turn a <code>Vector</code> of methods into an array of methods
   */
  private static java.lang.reflect.Method[]
      getMethods(java.util.Vector vm) {
    java.lang.reflect.Method ma[] =
        new java.lang.reflect.Method[vm.size()];
    vm.copyInto(ma);
    return ma;
  }

  public Class[] getReturnTypes() {
    Method m[] = getMethods();
    Class ca[] = new Class[m.length];
    for (int i = 0; i < m.length; i++)
      ca[i] = m[i].getReturnType();
    return ca;
  }


  /**
   return the internally held data as an array of methods;
   */
  public java.lang.reflect.Method[] getMethods() {
    return getMethods(v);
  }

  /**
   Return all the methods in the array that
   are not contained in the method list.
   */
  public java.lang.reflect.Method[]
      filter(java.lang.reflect.Method m[]) {
    MethodList ml = new MethodList();
    for (int i = 0; i < m.length; i++) {
      java.lang.reflect.Method u = m[i];
      if (!containedBy(u))
        ml.add(u);
      else
        System.out.println("// removed:" + u);
    }
    return ml.getMethods();
  }

  /**
   get number of methods in list
   */
  public int size() {
    return v.size();
  }

  public java.lang.reflect.Method elementAt(int i) {
    return (java.lang.reflect.Method) v.elementAt(i);
  }

  public void add(java.lang.reflect.Method m) {
    v.addElement(m);
  }

  public void add(java.lang.reflect.Method m[]) {
    for (int i = 0; i < m.length; i++)
      v.addElement(m[i]);
  }

  /**
   determine if two methods are equal.
   If they are non-null, have the same names
   and parameter lists, then they are equal.
   */
  public static boolean equals(java.lang.reflect.Method m1,
                               java.lang.reflect.Method m2) {
    if (m1 == null)
      return false;
    if (m2 == null)
      return false;
    if (!m1.getName().equals(m2.getName()))
      return false;

    Class[] p1 = m1.getParameterTypes();
    Class[] p2 = m2.getParameterTypes();

    if (p1.length != p2.length)
      return false;

    for (int i = 0; i < p1.length; i++)
      if (p1[i] != p2[i])
        return false;
    return true;
  }
}