package com.oreilly.jent.annotation.j2se;

/**
 * In general, you may use the code in this book in your programs and 
 * documentation. You do not need to contact us for permission unless 
 * you're reproducing a significant portion of the code. For example, 
 * writing a program that uses several chunks of code from this book does 
 * not require permission. Selling or distributing a CD-ROM of examples 
 * from O'Reilly books does require permission. Answering a question by 
 * citing this book and quoting example code does not require permission. 
 * Incorporating a significant amount of example code from this book into 
 * your product's documentation does require permission.
 * 
 * We appreciate, but do not require, attribution. An attribution usually 
 * includes the title, author, publisher, and ISBN. For example: 
 * 
 *   "Java Enterprise in a Nutshell, Third Edition, 
 *    by Jim Farley and William Crawford 
 *    with Prakash Malani, John G. Norman, and Justin Gehtland. 
 *    Copyright 2006 O'Reilly Media, Inc., 0-596-10142-2."
 *  
 *  If you feel your use of code examples falls outside fair use or the 
 *  permission given above, feel free to contact us at 
 *  permissions@oreilly.com.
 */

import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class LearnProcessor {

    static private PrintWriter sOut = new PrintWriter(System.out);
    
    public LearnProcessor() {
        super();
    }
    
    public static void main(String[] args) {
        if (args.length < 2) {
            System.err.println("USAGE: LearnProcessor <classname> <javadoc base>");
            System.exit(1);
        }
        String targetClassname = args[0];
        String javadocBase = args[1];
        
        try {
            // Lookup the class provided in the arguments
            Class targetClass = Class.forName(targetClassname);
            // Output the page header and start the table structure. 
            // If the class is annotated with a Learn tag, include the 
            // notation in the table as well.
            if (targetClass.isAnnotationPresent(Learn2.class)) {
                Learn2 annot = 
                    (Learn2)targetClass.getAnnotation(Learn2.class);
                outputHeader(targetClass, annot.value());
            }
            else {
                outputHeader(targetClass, null);
            }
            // Check each member variable on the class, and output 
            // any notations found
            Field[] fields = targetClass.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                if (fields[i].isAnnotationPresent(Learn2.class)) {
                    Learn2 annot = 
                        (Learn2)fields[i].getAnnotation(Learn2.class);
                    outputFieldNotation(fields[i], annot.value());
                }
            }
            // Check each constructor on the class, and output a notation
            // for any that have a Learn annotation
            Constructor[] cons = targetClass.getConstructors();
            for (int i = 0; i < cons.length; i++) {
                if (cons[i].isAnnotationPresent(Learn2.class)) {
                    Learn2 annot = 
                        (Learn2)cons[i].getAnnotation(Learn2.class);
                    outputConstructorNotation(cons[i], annot.value());
                }
            }
            // Check each method on the class, and output a notation
            // for any methods that have a Learn annotation
            Method[] methods = targetClass.getMethods();
            for (int i = 0; i < methods.length; i++) {
                if (methods[i].isAnnotationPresent(Learn2.class)) {
                    Learn2 annot = 
                        (Learn2)methods[i].getAnnotation(Learn2.class);
                    outputMethodNotation(methods[i], annot.value());
                }
            }
            // Print the page footer
            outputFooter(targetClass);
        }
        catch (ClassNotFoundException cnfe) {
            System.err.println("Class \"" + targetClassname + "\" not found");
        }
    }
    
    private static void outputHeader(Class target, String notation) {
        String title = "Educational highlights for <div class=\"code\">" 
                       + target.getName() + "</div>";
        sOut.println("<HTML><HEAD>");
        sOut.println("  <TITLE>" + title + "</TITLE>");
        sOut.println("  <link href=\"styles/learn-annotations.css\" rel=\"stylesheet\" type=\"text/css\">");
        sOut.println("</HEAD>");
        sOut.println("<BODY>");
        sOut.println("<div class=\"type\">" + title);
        if (notation != null) {
            sOut.println("  <div class=\"typeNotation\">" + notation + "</div>");
        }
    }
    
    private static void outputConstructorNotation(Constructor target, String notation) {
        String title = target.toString();
        sOut.println("  <div class=\"method\">Constructor<br><div class=\"code\">" 
                     + title + "</div>");
        if (notation != null) {
            sOut.println("    <div class=\"methodNotation\">" + notation
                         + "</div>");
        }
        sOut.println("  </div>");
    }
    
    private static void outputMethodNotation(Method target, String notation) {
        String title = target.toString();
        sOut.println("  <div class=\"method\">Method<br><div class=\"code\">" 
                     + title + "</div>");
        if (notation != null) {
            sOut.println("    <div class=\"methodNotation\">" + notation
                         + "</div>");
        }
        sOut.println("  </div>");
    }
    
    private static void outputFieldNotation(Field target, String notation) {
        String title = target.toString();
        sOut.println("  <div class=\"field\">Member<br><div class=\"code\">" 
                     + title + "</div>");
        if (notation != null) {
            sOut.println("    <div class=\"fieldNotation\">" + notation 
                         + "</div>");
        }
        sOut.println("  </div>");
    }
    
    private static void outputFooter(Class target) {
        sOut.println("</div>");
        sOut.println("</BODY>");
        sOut.println("</HTML>");
        sOut.flush();
    }
}
