// Purpose.  Complete API for ctors, methods, and fields [Flanagan97b, p258]

import java.lang.reflect.*;

public class ReflectShowClassAll {
   public static void main( String[] args ) throws ClassNotFoundException {
      Class c = null;
      try {
         c = Class.forName( args[0] );
      } catch (ClassNotFoundException e) { System.out.println( e ); }
      displayClass( c );
   }
   public static void displayClass(Class c) {
      // Print modifiers, type (class or interface), name and superclass.
      if (c.isInterface())
         // The modifiers will include the "interface" keyword here
         System.out.print( Modifier.toString( c.getModifiers() ) + " "
            + c.getName() );
      else if (c.getSuperclass() != null)
         System.out.print( Modifier.toString( c.getModifiers() ) + " class "
            + c.getName() + " extends " + c.getSuperclass().getName() );
      else
         System.out.print( Modifier.toString( c.getModifiers() ) + " class "
            + c.getName() );
        
      // Print interfaces or super-interfaces of the class or interface.
      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() );
      }  }
      System.out.println( " {" );                  // Begin class member listing

      // Now look up and display the members of the class.
      System.out.println( "   // Constructors" );
      Constructor[] constructors = c.getDeclaredConstructors();
      for (int i = 0; i < constructors.length; i++)      // Display constructors
         print_method_or_constructor( constructors[i] );

      System.out.println( "   // Methods" );
      Method[] methods = c.getDeclaredMethods();        // Look up methods
      for (int i = 0; i < methods.length; i++)          // Display them
         print_method_or_constructor( methods[i] );

      System.out.println( "   // Fields" );
      Field[] fields = c.getDeclaredFields();           // Look up fields
      for (int i = 0; i < fields.length; i++)           // Display them
         print_field( fields[i]  );

      System.out.println( "}" );                     // End class member listing
   }

   /* Return the name of an interface or primitive type, handling arrays. */
   public static String getTypeName( Class t ) {
      String brackets = "";
      while (t.isArray()) {
         brackets += "[]";
         t = t.getComponentType();
      }
      return t.getName() + brackets;
   }

   /* Return a string version of modifiers, handling spaces nicely. */
   public static String modifiers( int m ) {
      if (m == 0) return "";
      else return Modifier.toString(m) + " ";
   }

   /* Print the modifiers, type, and name of a field */
   public static void print_field( Field f ) {
      System.out.println( "   " + modifiers( f.getModifiers() )
         + getTypeName( f.getType() ) + " " + f.getName() + ";" );
   }

   /* Print the modifiers, return type, name, parameter types and exception  **
   ** type of a method or constructor.  Note the use of the Member interface **
   ** to allow this method to work with both Method and Constructor objects  */
   public static void print_method_or_constructor( 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();
      }
      System.out.print( "   " + modifiers( member.getModifiers() )
         + ((returnType!=null) ? getTypeName(returnType) + " " : "")
         + member.getName() + "(" );
      for (int i = 0; i < parameters.length; i++) {
         if (i > 0) System.out.print( ", " );
         System.out.print( getTypeName( parameters[i]) );
      }
      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( getTypeName( exceptions[i] ) );
      }
      System.out.println( ";" );
}  }

// C:> java ReflectShowClassAll java.util.StringTokenizer
// public class java.util.StringTokenizer extends java.lang.Object
//                                        implements java.util.Enumeration {
//    // Constructors
//    public java.util.StringTokenizer(java.lang.String);
//    public java.util.StringTokenizer(java.lang.String, java.lang.String);
//    public java.util.StringTokenizer(java.lang.String, String, boolean);
//    // Methods
//    public int countTokens();
//    public boolean hasMoreElements();
//    public boolean hasMoreTokens();
//    public java.lang.Object nextElement();
//    public java.lang.String nextToken();
//    public java.lang.String nextToken(java.lang.String);
//    private void skipDelimiters();
//    // Fields
//    private int currentPosition;
//    private int maxPosition;
//    private java.lang.String str;
//    private java.lang.String delimiters;
//    private boolean retTokens;
// }
