import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Member;
import java.lang.reflect.Field;
import java.lang.ClassNotFoundException;

public class ShowClass {
	public static void main(String[] args) {
   	try {
   		printClass( Class.forName(args[0]) );
   	} catch (ClassNotFoundException cnfe) {
   		System.out.println("cannot find class "+args[0]);
   	} //catch
  	} //main()
// ----------------------------------------------------------------------------
	public static void printClass(Class c) {
   	Package pck = c.getPackage();
   	if ( pck != null )
   		System.out.println("package "+pck.getName()+";" );

   	if (c.isInterface()) {
	   	System.out.print(Modifier.toString(c.getModifiers()) + " "+ c.getName());
    	} 	else
      	System.out.print(Modifier.toString(c.getModifiers()) + " class " +
                       c.getName() +
                       " extends " + c.getSuperclass().getName());

    	Class[] interfaces = c.getInterfaces();
    	if ((interfaces != null) && (interfaces.length > 0)) {
      	if (c.isInterface())
      		System.out.println(" extends ");
      	else
      		System.out.print(" implements ");
      	for(int i = 0; i < interfaces.length; i++) {
        		if (i > 0)
        			System.out.print(", ");
        		System.out.print(interfaces[i].getName());
      	} //for
    	} //if
    	System.out.println("\n{");

    	Constructor[] constructors = c.getDeclaredConstructors();
		if ( constructors.length > 0 ) {
    		System.out.println("   //Constructors");
    		for(int i = 0; i < constructors.length; i++)
      		printOperation(constructors[i]);
		} //if
		constructors = null;

		Class[] classes = c.getDeclaredClasses();
		if (classes.length > 0) {
    		System.out.println("   //Inner Classes");
			for (int i=0; i < classes.length; i++) {
				if (classes[i].isInterface() == false ) {
					printClass(classes[i] );
					System.out.print("\n");
				} //if
			} //for
    		System.out.println("   //Inner Interfaces");
			for (int i=0; i < classes.length; i++) {
				if (classes[i].isInterface() == true ) {
					printClass(classes[i] );
					System.out.print("\n");
				} //if
			} //for
		} //if
		classes = null;

    	Field[] fields = c.getDeclaredFields();
    	if ( fields.length > 0) {
    		System.out.println("   //Attributes");
    		for(int i = 0; i < fields.length; i++)
      		printAttribute(fields[i]);
		} //if
		fields = null;


    	Method[] operations = c.getDeclaredMethods();
    	if ( operations.length > 0 ) {
	  		System.out.println("   //Operations");
	    	for(int i = 0; i < operations.length; i++)
	      	printOperation(operations[i]);
  		} //if
  		operations = null;

    	System.out.print("} //end ");
    	if ( c.isInterface() )
    		System.out.print("interface ");
    	else
    		System.out.print("class ");
    	System.out.print( c.getName() );
  	} //printClass(Class)
// ----------------------------------------------------------------------------
	public static String typename(Class t) {
   	String brackets = "";
    	while(t.isArray()) {
      	brackets += "[]";
      	t = t.getComponentType();
    	} //while
 	   return t.getName() + brackets;
  	} //typename(Class)
// ----------------------------------------------------------------------------
  	public static String modifiers(int m) {
		if (m == 0)
	  		return "";
	   else
	   	return Modifier.toString(m) + " ";
  	} //modifiers(int)
// ----------------------------------------------------------------------------
  	public static void printAttribute(Field f) {
  		System.out.print("  " + modifiers(f.getModifiers()) + typename(f.getType()) + " " + f.getName() + ";     //"+f.getType().getName()+" is ");

		if ( (f.getType()).isInterface() )
			System.out.println("an interface");
		else {
			if ( f.getType().isPrimitive() )
				System.out.println("a primitive type");
			else {
				if ( f.getType().isArray() )
					System.out.println("an array");
				else
					System.out.println("a class");
			} //else
		} //else
	} //printAttribute(Field)
// ----------------------------------------------------------------------------
	public static void printOperation(Member member) {
  		Class returntype=null, parameters[], exceptions[];

	   if (member instanceof Method) {
	   	Method m = (Method) member;
	      returntype = m.getReturnType();
	      parameters = m.getParameterTypes();
	      exceptions = m.getExceptionTypes();
	   } else {
	   	Constructor c = (Constructor) member;
	      parameters = c.getParameterTypes();
	      exceptions = c.getExceptionTypes();
	   } //else

	   System.out.print("  " + modifiers(member.getModifiers()) + ((returntype!=null)? typename(returntype)+" " : "") + member.getName() + "(");
	   for(int i = 0; i < parameters.length; i++) {
	   	if (i > 0)
	   		System.out.print(", ");

	      System.out.print(typename(parameters[i]));
	   } //for

	   System.out.print(")");

	   if (exceptions.length > 0)
	   	System.out.print(" throws ");

	   for(int i = 0; i < exceptions.length; i++) {
	   	if (i > 0)
	   		System.out.print(", ");

	      System.out.print(typename(exceptions[i]));
	   } //for

	   System.out.println(";");
	} //printOperation(Member)
} //class ShowClass

// --------------------------------------------
interface TestInterface {
} //interface TestInterface

class TestClass {
	public 		TestInterface  i1;
	private 		TestClass  c1;
	protected  	int p1;
	int[]			ta1;
	int[][] 		tam1;

	class Inner {
		int i;
		class InnerInner {
			int j;
		} //class InnerInner
	} //class Inner
	interface InnerInterface {
	} //interface InnerInterface

	private TestClass testc() {
		return new TestClass() {
			public void hello() {
				System.out.println("overridden test!");
			} //hello()
		}; //class TestClass
	} //test()
} //class TestClass