/**************************************************************************
/* Doclet for the bb.todo-Tag. Dump all todo-items to stdout.
/*
/* Copyright (c) 2004 by Bernhard Bablok (mail@bablokb.de)
/*
/* This library is free software; you can redistribute it and/or modify
/* it under the terms of the GNU Lesser General Public License as published
/* by  the Free Software Foundation; either version 2 of the License or
/* (at your option) any later version.
/*
/* This library is distributed in the hope that it will be useful, but
/* WITHOUT ANY WARRANTY; without even the implied warranty of
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
/* GNU Lesser General Public License for more details.
/*
/* You should have received a copy of the GNU Lesser General Public License
/* along with this library; see the file COPYING.LESSER.  If not, write to
/* the Free Software Foundation Inc., 59 Temple Place - Suite 330,
/* Boston, MA  02111-1307 USA
/**************************************************************************/

package de.bablokb.tools;

import java.io.*;
import com.sun.javadoc.*;

/**
   Doclet for the bb.todo-Tag. Dumps all bb.todo-Tags to stdout. You can
   subclass the {@link dumpTag}-method to create another kind of output.

  <p>The doclet accepts commandline-parameters: <code>-tag tagname</code>
  specifies the tag and <code>-o file</code> specifies the destination
  file. The default ist the bb.todo-tag and stdout.</p>

   @version $Revision: 1.1 $
   @author  $Author: bablokb $
*/

public class BBToDoDoclet {

  private static String iTagName = "@bb.todo";
  private static String iOutFile = null;
  private static PrintWriter iWriter = null;
  
  ////////////////////////////////////////////////////////////////////////////

  /**
     Entry point for doclet (required by Doclet-API).

     @param root The root of the documents

     @returns Always returns true
  */

  public static boolean start(RootDoc root){
    parseOptions(root.options());
    ClassDoc[] classes = root.classes();
    for (int i=0; i < classes.length; i++) {
      dumpTag(classes[i].tags(iTagName),classes[i].qualifiedName());
      parseClass(classes[i]);
    }
    return true;
  }

  ////////////////////////////////////////////////////////////////////////////

  /**
     Iterate over all containing classes, fields, constructors and methods.
     This methods calls itself recursively for all inner classes.

     @param clazz The ClassDoc-object for the current class.
  */

  private static void parseClass(ClassDoc clazz) {
    // inner classes
    ClassDoc[] classes = clazz.innerClasses();
    for (int i=0; i < classes.length; i++) {
      dumpTag(classes[i].tags(iTagName),classes[i].qualifiedName());
      parseClass(classes[i]);
    }
   
    // fields
    FieldDoc[] fields = clazz.fields();
    for (int i=0; i < fields.length; i++) {
      dumpTag(fields[i].tags(iTagName),fields[i].qualifiedName());
    }

    // constructors
    ConstructorDoc[] constructors = clazz.constructors();
    for (int i=0; i < constructors.length; i++) {
      dumpTag(constructors[i].tags(iTagName),constructors[i].qualifiedName());
    }

    // methods
    MethodDoc[] methods = clazz.methods();
    for (int i=0; i < methods.length; i++) {
      dumpTag(methods[i].tags(iTagName),methods[i].qualifiedName());
    }
  }

  ////////////////////////////////////////////////////////////////////////////

  /**
     Dump the contents of the bb.todo-tag to stdout. Override this method
     if you want to change the output-format (e.g. you could output some
     sql-statements to add the list of todos to a database).
  */

  public static void dumpTag(Tag[] tags, String qualifiedName) {
    try {
      if (iWriter == null) {
	if (iOutFile == null)
	  iWriter = new PrintWriter(System.out,true);
	else                                             // append, flush
	  iWriter = new PrintWriter(new FileWriter(iOutFile,true),  true);
      }
    } catch (IOException e) {
      throw new Error(e);
    }
    for (int i=0; i < tags.length; i++) {
      iWriter.println(qualifiedName + ": " + tags[i].text());
    } 
  }

  ////////////////////////////////////////////////////////////////////////////

  /**
     Parse commandline-options.

     @param options Array of option-strings and arguments

  */

  private static void parseOptions(String[][] options) {
    for (int i = 0; i < options.length; i++) {
      String[] opt = options[i];
      if (opt[0].equals("-tag"))
	iTagName = "@" + opt[1];
      else if (opt[0].equals("-o"))
	iOutFile = opt[1];
    }
  }

  ////////////////////////////////////////////////////////////////////////////

  /**
     Define options length (required by Doclet-API).

  */

  public static int optionLength(String option) {
    if(option.equals("-tag") || option.equals("-o"))
      return 2;
    else
      return 0;
  }
}

