import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class objectInfo {

	public static void main(String[] args) {
		System.out.println("Test Run for printObjectInfo");
		System.out.println("\n*************************************************");
		System.out.println("This is information for a two-dimensional array of ints:");
		printObjectInfo(new int[4][3]);
		System.out.println("\n*************************************************");
		System.out.println("This is information for a String object:");
		printObjectInfo(new String("Test"));
		System.out.println("\n*************************************************");
		System.out.println("This is information for a Integer object:");
		printObjectInfo(new Integer(5));
		System.out.println("\n*************************************************");
		System.out.println("This is information for a ArrayList object:");
		printObjectInfo(new java.util.ArrayList());
		
	}

	public static void printObjectInfo(Object o){
		System.out.println("Object Information\n");

		Class cls = o.getClass();

		//Check if array, then print out array information
		if(cls.isArray()){
			String compType = cls.getComponentType().getName();

			System.out.println("Object is an array");
			System.out.println("Array: "+cls.getName()
				+" Component Type:"+compType);
		}
		else{
			System.out.println("Class:"+cls.getName());
			System.out.println("Class Modifiers:" +
				Modifier.toString(cls.getModifiers())+'\n');
			printMethodInfo(cls);
			printFieldInfo(cls,o);
		}
		//using similar approch we can get constructor information
	}

	public static void printMethodInfo(Class cls){
		//gets public methods of class cls
		Method[] publicMethods = cls.getMethods();
		if(publicMethods.length>0){
			System.out.println("Public Methods");

			for(Method mthds: publicMethods){

				/*gets modifiers for each method
				 *modifier value is returned as a int
				 *use toString to convert int to string */

				int mod = mthds.getModifiers();
				System.out.print(Modifier.toString(mod)+" ");

				System.out.print(mthds.getReturnType().getName()+" ");
				System.out.print(mthds.getName()+"(");

				Class[] parTypes = mthds.getParameterTypes();
				StringBuffer parInfo= new StringBuffer();
				for(Class par: parTypes){
					parInfo.append(par.getName()+',');
				}
//				delete the last comma-for printing
				int parLeng=parInfo.length();
				if(parLeng!=0){
					parInfo.deleteCharAt(parLeng-1); 
				}
				System.out.println(parInfo.toString()+")");
			}
		}
	}

	public static void printFieldInfo(Class cls, Object o){
		Field[] publicFields = cls.getFields();
		if(publicFields.length>0){
			System.out.println("\nPublic Fields");

			for(Field field: publicFields){
				String fieldName = field.getName();
			    String fieldType = field.getType().getName();;
				Object value = null;
				try {
					value = field.get(o);
				} catch (Exception e) {
					System.out.println(e);
				}
				System.out.println("Name: " + fieldName +
					" Type: " + fieldType + " Value: "+value);
			}
		}
	}
}
