/* * THIS IS FREE SOFTWARE. * Permission to use, copy, modify, and distribute this software and documentation * in all settings is hereby granted, provided that NO FEE is charged for this * software and provided that this copyright notice appears in all copies of any * software which is or includes a copy or modification of this software. In all * advertising materials, documentation, and publications mentioning features or * use of this software you must credit the author. * * JACK PERDUE MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, * OR NON-INFRINGEMENT. JACK PERDUE SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY THE USER AS A RESULT OF USING, MODIFYING OR DISTRIBUTING * THIS SOFTWARE OR ITS DERIVATIVES. * * Developed by Jack Perdue (a.k.a. Silicon Slick) - si_slick@cy-net.net * Copyright (c) 1998 Silicon Slick's Software, Supplies and Support Services * All Rights Reserved */ import java.io.*; import java.util.StringTokenizer; /** * Adds javadoc comment templates to source by using output of * iDoc by Reto Kramer. * Currently adds class/interface/variable/method descriptor templates, * method parameter templates and method return value templates. * Additionally generates javadoc comments indicating obsolete * and nonjavadoc tags. See the variable * unjavadocumentedvariablefortesting * and the method testAddJavaDoc * below for an example. *

* Typical usage is: *

 *    java iDoc.Tools -s -n -t %classname%.java >%classname%.idoc
 *    java AddJavaDoc %classname%.idoc %classname%.java [%header_file%]
 * 
*

* The output (source with javadoc templates) PROVIDED NOTHING BAD HAPPENS is * put into %classname%.jdoc. I strongly recommend verification (a compile * and run of javadoc should be sufficient) before toasting the original. *

* If you run it on this class, it should look something like: *

 * C:\myJava>java iDoc.Tool -s -n -t AddJavaDoc.java >AddJavaDoc.idoc
 * C:\myJava>java AddJavaDoc AddJavaDoc.idoc AddJavaDoc.java
 * 0  306 iDoc.Variable Title
 * 1  311  NONJAVADOC
 * 2  311  OBSOLETE iDoc.Method params obsoleteparm
 * 3  311 iDoc.Method Title
 * 4  311 iDoc.Method params missingparm returns
 * 
* optionally *
 * C:\myJava>copy AddJavaDoc.jdoc t.java
 * C:\myJava>javadoc -private -author -version -notree t.java
 * 
* will generate AddJavaDoc.html which will look very much like what * you are reading now. *

* VERIFY THE .JDOC BEFORE COPYING BACK TO THE .JAVA -- * I think this code is correct for now, but iDoc could change or * an exception could happen and if you didn't verify it with * at least a compile and a run of javadoc then you will * lose your original source when copying the .jdoc to .java. * Backups are always good too. *

* It should System.exit(1) if it encounters a problem, and you can test * this in the shell (eg. IF ERRORLEVEL 1 in DOS) to see if it completed * successfully. Again, there are no guarantees -- keep backups of your source. *

* Just as an example, here is the .BAT file I use. *

 * java iDoc.Tool -s -n -t %1.java >%1.idoc
 * if errorlevel 1 goto :errorexit
 * java AddJavaDoc %1.idoc %1.java c:\myjava\freeheader.txt
 * if errorlevel 1 goto :errorexit
 * copy %1.java %1.jbak
 * if errorlevel 1 goto :errorexit
 * copy %1.jdoc %1.java
 * echo Completed...
 * goto :exit
 * :errorexit
 * echo ERROR!!!
 * :exit
 * echo exiting.
 * 
* Obviously, I make backups of the source before running it (in addition to * the one it makes) JUST IN CASE. *

* Ideally, the source is available with this * page by clicking on "the source". *

*

Be sure to check AddJavaDoc's "home page" at * http://www.cs.tamu.edu/people/jkp2866/java/AddJavaDoc/AddJavaDoc.html for updates. *

* Revisions: *

* @author Jack Perdue j-perdue@tamu.edu si_slick@cy-net.net * @version 0.0004 13 Jul 1998 **/ public class AddJavaDoc { /** * Error file size limit **/ static int MAXREADFORMARK = 128 * 1024; /** * maximum number of parameters a method can have **/ static int MAXPARAMS = 20; /** * code for iDoc unlabeled class error **/ final static int CLASSTITLE = 1; /** * code for iDoc unlabeled interface error **/ final static int INTERFACETITLE = 2; /** * code for iDoc unlabeled variable error **/ final static int VARIABLETITLE = 3; /** * code for iDoc unlabeled method error **/ final static int METHODTITLE = 4; /** * code for iDoc method parameters error **/ final static int METHODPARAMVOID = 11; /** * code for iDoc method parameters and return error **/ final static int METHODPARAMRETURN = 12; /** * code for iDoc non-javadoc comment error **/ final static int NONJAVADOC = 21; /** * code for iDoc obsolete parameter tag error **/ final static int OBSOLETETAG = 22; /** * indicates user needs to provide info for javadoc **/ static String FILL = "+XX+"; /** * indicates user needs to service a parameter tag **/ static String FILLOBSOLETETAG = "OBSOLETETAG"; /** * indicates user needs to service some unrecognized javadoc comments **/ static String FILLNONJAVADOC = "NONJAVADOC"; /** * iDoc Scanner exception tag **/ static String IDOCSCANNEREXCEPTIONTAG = "Scanner exception"; /** * iDoc class tag **/ static String IDOCCLASSTAG = "iDoc.Class"; /** * iDoc interface tag **/ static String IDOCINTERFACETAG = "iDoc.Interface"; /** * iDoc variable tag **/ static String IDOCVARIABLETAG = "iDoc.Variable"; /** * iDoc method tag **/ static String IDOCMETHODTAG = "iDoc.Method"; /** * iDoc error tag **/ static String IDOCERRORTAG = "error"; /** * iDoc non-javadoc comment tag **/ static String IDOCNONJAVADOCTAG = "non-javadoc"; /** * iDoc comment tag **/ static String IDOCCOMMENTTAG = "comment"; /** * iDoc missing tag **/ static String IDOCMISSINGTAG = "missing"; /** * iDoc obsolete tag **/ static String IDOCOBSOLETETAG = "obsolete"; /** * iDoc param tag **/ static String IDOCPARAMTAG = "param"; /** * iDoc return tag **/ static String IDOCRETURNTAG = "return"; /** * Disable bad comment check. Change if desired. * However, enabling will cause errors when processing this class. **/ final static boolean dobadcommentcheck = false; /** * Disallowed comment starter (change if desired) **/ final static String BADCOMMENT = "/***"; /** * javadoc start comment **/ final static String JAVADOCSTARTCOMMENT = "/**"; /** * javadoc middle comment **/ final static String JAVADOCMIDDLECOMMENT = " * "; /** * javadoc endcomment **/ final static String JAVADOCENDCOMMENT = "**/"; /** * javadoc parameter tag **/ final static String JAVADOCPARAM = "@param"; /** * javadoc return tag **/ final static String JAVADOCRETURN = "@return"; /** * javadoc author tag **/ final static String JAVADOCAUTHOR = "@author"; /** * javadoc version tag **/ final static String JAVADOCVERSION = "@version"; /** * customized javadoc author tag (hard-coded for now -- needs servicing) **/ static String authortag = JAVADOCAUTHOR + " Duke (service AddJavaDoc's authortag)"; /** * customized javadoc version tag (hard-coded for now -- needs servicing) **/ static String versiontag = JAVADOCVERSION + " 0.001 01 Jan 1970 (service AddJavaDoc's version tag)"; /** * line number the errorcode occurred **/ int lineno; /** * code for iDoc error **/ int errorcode; /** * parameters for method **/ String [] params; /** * Constructs an iDoc errorcode entry (a future javadoc comment) * @param lineno line number in source where javadoc comments are needed * @param errorcode type of iDoc error * @param params method parameters (to generate lines like this one) **/ public AddJavaDoc(int lineno, int errorcode, String [] params) { this.errorcode = errorcode; this.lineno = lineno; this.params = params; } /** * Adds javadoc comments to code. * @param args iDoc filename, source filename, header filename **/ public static void main (String [] args) { if (args.length >= 2) { // if specified, load given file AddJavaDoc [] errors = iDocErrors(args[0]); String [] header = null; if( args.length == 3) { header = readHeaders(args[2]); } addJavaDocs(args[1], errors, header); } else { System.out.println("Usage - java AddJavaDoc <.java source> [
]"); System.exit(1); } System.exit(0); // everything was okay(???) } // main() // some testing material (next line tests tabbed indentation as well) static final int unjavadocumentedvariablefortesting=0; // needs title /** * @param obsoleteparm this should generate an obsolete error in iDoc * @parm badparm this should generate a nonjavadoc error in iDoc **/ final int testAddJavaDoc(int missingparm) { // tests AddJavaDoc's interface with iDoc return 1; // note this method needs a javadoc title } /** * reads header (copyright) file into buffer * @param headername name of header file * @return buffer containing text of header file **/ static String [] readHeaders( String headername) { try { FileInputStream is = new FileInputStream(headername); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr, MAXREADFORMARK); br.mark(MAXREADFORMARK); int linecounter = 0; String line; while ( null != (line = br.readLine())) { ++linecounter; } br.reset(); String [] headers = new String [linecounter]; linecounter = 0; while ( null != (line = br.readLine())) { headers[linecounter] = new String(line); ++linecounter; } br.close(); return(headers); } catch( Exception e) { System.out.println("Exception " + e); return null; } } // readHeaders() /** * parses iDoc error * @param line line of text from iDoc errorcode listing * @return a iDoc errorcode (future javadoc addition) **/ static public AddJavaDoc parseError(String line) { StringTokenizer st = new StringTokenizer(line, ", :[]"); String s; if( st.hasMoreTokens()) s = st.nextToken(); // file name else return null; if( st.hasMoreTokens())s = st.nextToken().trim(); // line number else return null; int lineno; try{ lineno = new Integer(s).intValue(); } catch(Exception e) { System.out.println("Exception: " + e); System.out.println("Ignoring: "+line); return null; } if( st.hasMoreTokens())s = st.nextToken(); // "idoc" else return null; if( st.hasMoreTokens())s = st.nextToken().trim(); // "error" or not else return null; int errorcode = 0; int paramcounter = 0; String [] maxparams = null; if (s.equals(IDOCERRORTAG)) { if( st.hasMoreTokens()) s = st.nextToken().trim(); // iDoc.Class or .Variable or .Method else return null; if (s.equals(IDOCCLASSTAG)) { // set assuming it will be a comment title error errorcode = CLASSTITLE; } else if (s.equals(IDOCINTERFACETAG)) { errorcode = INTERFACETITLE; } else if (s.equals(IDOCVARIABLETAG)) { errorcode = VARIABLETITLE; } else if (s.equals(IDOCMETHODTAG)) { errorcode = METHODTITLE; } else { System.out.println("Unparsable iDoc line - " + line); System.exit(1); } if( st.hasMoreTokens()) s = st.nextToken().trim(); // Class / method / variable name else return null; if( st.hasMoreTokens()) s = st.nextToken().trim(); // "comment" or "non-javadoc" else return null; if (s.equals(IDOCNONJAVADOCTAG)) { errorcode = NONJAVADOC; } else if(!s.equals(IDOCCOMMENTTAG)) { return null; // unknown iDoc line } } else { // method param error if (s.equals(IDOCMETHODTAG)) { errorcode = METHODPARAMVOID; if( st.hasMoreTokens()) s = st.nextToken(); // method name else return null; if( st.hasMoreTokens()) s = st.nextToken(); // "missing" or "obsolete" else return null; if( s.equals(IDOCMISSINGTAG)) { errorcode = METHODPARAMVOID; } else if (s.equals(IDOCOBSOLETETAG)) { errorcode = OBSOLETETAG; } else { return null; // unrecognized iDoc error } if( st.hasMoreTokens()) s = st.nextToken(); // "tags" else return null; maxparams = new String [MAXPARAMS]; while (st.hasMoreTokens()) { s = st.nextToken().trim(); if (s.equals(IDOCPARAMTAG)) { if( st.hasMoreTokens()) s = st.nextToken().trim(); maxparams[paramcounter] = s; ++paramcounter; } else if (s.equals( IDOCRETURNTAG)) { if( errorcode == METHODPARAMVOID) errorcode = METHODPARAMRETURN; } } } else { return null; // unrecognized iDoc error } } if( maxparams != null) { String [] foundparams = new String[paramcounter]; System.arraycopy( maxparams, 0, foundparams, 0, paramcounter); maxparams = foundparams; } return new AddJavaDoc(lineno, errorcode, maxparams); } // parseError() /** * reads iDoc errorcode file * @param idocname name of iDoc errorcode listing * @return list of iDoc errors (future javadoc additions) **/ static AddJavaDoc [] iDocErrors( String idocname) { try { FileInputStream is = new FileInputStream(idocname); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr, MAXREADFORMARK); br.mark(MAXREADFORMARK); int linecounter = 0; String line; while ( null != (line = br.readLine())) { ++linecounter; } br.reset(); AddJavaDoc [] errors = new AddJavaDoc [linecounter]; int errorcounter = 0; while ( null != (line = br.readLine())) { if( ! line.startsWith(IDOCSCANNEREXCEPTIONTAG)) { AddJavaDoc parseerror = parseError(line); if (parseerror != null) { errors[errorcounter] = parseerror; ++errorcounter; } } } AddJavaDoc [] trimmederrors = new AddJavaDoc[errorcounter]; System.arraycopy( errors, 0, trimmederrors, 0, errorcounter); errors = trimmederrors; sortErrors(errors); return errors; } catch( Exception e) { System.out.println("Exception " + e); return null; } } // iDocErrors() /** * adds javadoc comments to source code * @param srcname name of source code (.java) file * @param errors list of iDoc errors (future javadoc additions) * @param headers new header for source file **/ static void addJavaDocs( String srcname, AddJavaDoc [] errors, String [] headers) { if( srcname.endsWith(".java")) { srcname = srcname.substring(0,srcname.length() - 5); } String dstname = srcname + ".jdoc"; srcname = srcname + ".java"; BufferedReader br = null; PrintWriter pw = null; try { FileInputStream fis = new FileInputStream(srcname); InputStreamReader isr = new InputStreamReader(fis); br = new BufferedReader(isr, MAXREADFORMARK); FileOutputStream fos = new FileOutputStream(dstname); OutputStreamWriter osw = new OutputStreamWriter(fos); pw = new PrintWriter(osw,true); } catch (Exception e) { System.out.println("Exception opening input/outputfiles " + e); System.exit(1); } if( headers != null) { for( int i = 0; i < headers.length; i++) { pw.println(headers[i]); } } int errorcounter = 0; int linecounter = 1; String line = null; try { line = br.readLine(); } catch (IOException ioe) { System.out.println("Error reading input file " + srcname + " " + ioe); System.exit(1); } while ( null != line) { if( dobadcommentcheck && (line.indexOf(BADCOMMENT) >= 0)) { System.out.println("Sorry... bad comment starter detected..." + BADCOMMENT + " modify this class if desired."); System.out.println(linecounter + " " + line); System.exit(1); } if( errorcounter < errors.length) { if( errors[ errorcounter].lineno == linecounter) { // determine indentation int indent = 0; String indentstring = ""; boolean done = false; while( ! done) { char c = line.charAt(indent); if( (c == ' ') || (c == '\t')) { indentstring = indentstring + c; } else { done = true; } ++indent; } pw.println(indentstring + JAVADOCSTARTCOMMENT); while ((errorcounter < errors.length) && (errors[ errorcounter].lineno == linecounter)) { AddJavaDoc thiserror = errors[ errorcounter]; String doc = indentstring + JAVADOCMIDDLECOMMENT; switch( thiserror.errorcode) { case CLASSTITLE: // fall through case INTERFACETITLE: String classdoc = doc + FILL; pw.println(classdoc); pw.println(doc); classdoc = doc + authortag; pw.println(classdoc); classdoc = doc + versiontag; pw.println(classdoc); break; case VARIABLETITLE: // fall through case METHODTITLE: doc = doc + FILL; pw.println(doc); break; case OBSOLETETAG: if( thiserror.params != null) { String paramdoc; for( int i = 0; i < thiserror.params.length; i++) { paramdoc = doc + FILLOBSOLETETAG + " " + thiserror.params[i] + " " + FILL; pw.println(paramdoc); } } break; case NONJAVADOC: doc = doc + FILLNONJAVADOC; pw.println(doc); break; case METHODPARAMVOID: // fall through case METHODPARAMRETURN: if( thiserror.params != null) { String paramdoc; for( int i = 0; i < thiserror.params.length; i++) { paramdoc = doc + JAVADOCPARAM + " " + thiserror.params[i] + " " + FILL; pw.println(paramdoc); } } if( thiserror.errorcode == METHODPARAMRETURN) { doc = doc + JAVADOCRETURN + " " + FILL; pw.println(doc); } break; default: System.out.println("Invalid errorcode code: " + thiserror.errorcode ); System.exit(1); break; } ++errorcounter; } pw.println(indentstring + JAVADOCENDCOMMENT); } } // end errorcounter < errors.length pw.println(line); ++linecounter; try { line = br.readLine(); } catch (IOException ioe) { System.out.println("Error reading input file " + srcname + " " + ioe); System.exit(1); } } // endwhile() try{ br.close(); pw.close(); } catch (Exception e) { System.out.println("Exception closing input/outputfiles " + e); System.exit(1); } } // addJavaDocs() /** * swaps two iDoc errors * @param errors list of iDoc errors * @param i errorcode to swap * @param j errorcode to swap **/ static void swap(AddJavaDoc [] errors, int i, int j) { AddJavaDoc tmp = errors[i]; errors[i] = errors[j]; errors[j] = tmp; return; } // swap() /** * sorts errors by line number and type * @param errors list of iDoc errors (future javadoc addition) **/ static void sortErrors( AddJavaDoc [] errors) { for( int i = 0; i < errors.length - 1; i++) { for( int j = i + 1; j < errors.length; j++) { if( errors[ i].lineno > errors[j].lineno) swap(errors, i, j); else if (errors[i].lineno == errors[j].lineno) { if ((errors[i].errorcode == METHODPARAMRETURN) || (errors[i].errorcode == METHODPARAMVOID)) swap(errors, i, j); } } } for( int i = 0; i < errors.length; i++) { System.out.println(i + " " + errors[i]); } } // sortErrors() /** * converts an iDoc errorcode (future javadoc addition) to a string * @return string describing iDoc errorcode (future javadoc addition) **/ public String toString() { String s = lineno + " "; switch( errorcode) { case CLASSTITLE: s = s + IDOCCLASSTAG + " Title "; break; case INTERFACETITLE: s = s + IDOCINTERFACETAG + " Title "; break; case VARIABLETITLE: s = s + IDOCVARIABLETAG + " Title "; break; case METHODTITLE: s = s + IDOCMETHODTAG + " Title "; break; case NONJAVADOC: s = s + " NONJAVADOC "; break; case OBSOLETETAG: s = s + " OBSOLETE "; // fall through case METHODPARAMVOID: // fall through case METHODPARAMRETURN: s = s + IDOCMETHODTAG + " "; if( params != null) { s = s + "params "; for( int i = 0; i < params.length; i++) { s = s + params[i] + " "; } } break; default: s = s + "Unknown error code"; break; } if (errorcode == METHODPARAMRETURN) s = s + "returns "; return s; } // toString() } // AddJavaDoc