package net.matrix_rad.skang; import com.sun.javadoc.*; // IGNORE WARNING. import java.lang.*; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; /** Skang extension doclet. * Compile and run this with a 1.4 JDK. * Keep this out of reach of the Ant javadoc target, * 'cause it uses 1.1 classes, which won't work with * the 1.4 stuff in here. * * @author David Seikel * @.copyright 2002 David Seikel * @version 1.3 final 2002-12-29 10:37:00 */ public class MakeSkangletDoclet extends Doclet // IGNORE WARNING. { public static int optionLength(String anOption) { if (anOption.equals("-d")) return 2; return 0; } public static boolean validOptions(String options[][], DocErrorReporter reporter) // IGNORE WARNING. { boolean foundDestOption = false; boolean foundSourceOption = false; for (int i = 0; i < options.length; i++) { String[] opt = options[i]; if (opt[0].equals("-d")) { if (foundDestOption) { reporter.printError("Only one -d option allowed."); return false; } else foundDestOption = true; } if (opt[0].equals("-sourcepath")) { if (foundSourceOption) { reporter.printError("Only one -suorcepath option allowed."); return false; } else foundSourceOption = true; } } if (!(foundDestOption && foundSourceOption)) reporter.printError("Usage: javadoc -sourcepath sourcepath -d destpath -doclet MakeSkangletDoclet ..."); return foundDestOption && foundSourceOption; } public static boolean start(RootDoc aRoot) // IGNORE WARNING. { System.out.println("Skang Doclet version 1.1\n"); System.out.println("Building Skanglets..."); ClassDoc classes[] = aRoot.classes(); String opts[][] = aRoot.options(); String source = ""; String dest = ""; for (int i = 0; i < opts.length; i++) { // These option names are forced on me by Ant, which had inherited // them from javadoc. Blame Sun. if (opts[i][0].equals("-sourcepath")) source = opts[i][1] + System.getProperty("file.separator").charAt(0); else if (opts[i][0].equals("-d")) dest = opts[i][1] + System.getProperty("file.separator").charAt(0); } /* Note, .help overrides the first sentence */ for (int i = 0; i < classes.length; i++) { String AUTHOR = ""; String COPYRIGHT = ""; String VERSION = ""; String USAGE = ""; String SKANG = ""; String DEFAULT = ""; String path = ""; String pack = ""; String name = classes[i].toString(); int pos = name.lastIndexOf('.'); if (pos != -1) { pack = name.substring(0, pos); path = name.substring(0, pos + 1).replace('.', System.getProperty("file.separator").charAt(0)); name = name.substring(pos + 1); } Tag[] authorTags = classes[i].tags("author"); Tag[] copyrightTags = classes[i].tags(".copyright"); Tag[] versionTags = classes[i].tags("version"); for (int k = 0; k < authorTags.length; k++) AUTHOR += authorTags[k].text(); for (int k = 0; k < copyrightTags.length; k++) COPYRIGHT += copyrightTags[k].text(); for (int k = 0; k < versionTags.length; k++) VERSION += versionTags[k].text(); MethodDoc[] methods = classes[i].methods(); for (int j = 0; j < methods.length; j++) { Tag[] paramTags = methods[j].tags("param"); Tag[] skangTags = methods[j].tags(".skang"); Tag[] helpTags = methods[j].tags(".help"); Tag[] argTags = methods[j].tags(".skangarg"); Tag[] reqTags = methods[j].tags(".required"); Tag[] shortTags = methods[j].tags(".shortcut"); Tag[] ownerTags = methods[j].tags(".owner"); Tag[] secureTags = methods[j].tags(".secure"); Tag[] firstTags = methods[j].firstSentenceTags(); if (skangTags.length > 0) { String help = escape((helpTags.length > 0) ? (helpTags[0].text()) : (firstTags[0].text()), false); for (int k = 0; k < skangTags.length; k++) { SKANG += "\t\t{\""; pos = skangTags[k].text().indexOf(" "); if (pos != -1) SKANG += skangTags[k].text().substring(0, pos); else SKANG += skangTags[k].text(); SKANG += "\", \"" + methods[j].name() + "\", \""; if (pos != -1) SKANG += skangTags[k].text().substring(pos + 1); SKANG += "\", \"" + help + "\", \""; if (ownerTags.length > 0) SKANG += ownerTags[0].text(); SKANG += "\", \""; if (secureTags.length > 0) SKANG += secureTags[0].text(); SKANG += "\"},\n"; } } if (argTags.length > 0) { String help = escape((helpTags.length > 0) ? (helpTags[0].text()) : (firstTags[0].text()), false); for (int k = 0; k < argTags.length; k++) { USAGE += "\t\t{\"" + argTags[k].text() + "\", \"" + methods[j].name() + "()\", \""; USAGE += ((reqTags.length > 0) ? "Y" : "N") + "\", \""; if (shortTags.length > 0) USAGE += shortTags[0].text(); USAGE += "\", null, \"" ; USAGE += help + "\", \""; if (ownerTags.length > 0) USAGE += ownerTags[0].text(); USAGE += "\", \""; if (secureTags.length > 0) USAGE += secureTags[0].text(); USAGE += "\"},\n"; } } } FieldDoc[] fields = classes[i].fields(); for (int j = 0; j < fields.length; j++) { Tag[] skangTags = fields[j].tags(".skangarg"); Tag[] defTags = fields[j].tags(".default"); Tag[] reqTags = fields[j].tags(".required"); Tag[] shortTags = fields[j].tags(".shortcut"); Tag[] helpTags = fields[j].tags(".help"); Tag[] ownerTags = fields[j].tags(".owner"); Tag[] secureTags = fields[j].tags(".secure"); Tag[] firstTags = fields[j].firstSentenceTags(); if (skangTags.length > 0) { String help = escape((helpTags.length > 0) ? (helpTags[0].text()) : (firstTags[0].text()), false); for (int k = 0; k < skangTags.length; k++) { USAGE += "\t\t{\"" + skangTags[k].text() + "\", \"" + fields[j].name() + "\", \""; USAGE += ((reqTags.length > 0) ? "Y" : "N") + "\", \""; if (shortTags.length > 0) USAGE += shortTags[0].text(); USAGE += "\", " + ((defTags.length > 0) ? (defTags[0].text()) : "null") + ", \"" ; USAGE += help + "\", \""; if (ownerTags.length > 0) USAGE += ownerTags[0].text(); USAGE += "\", \""; if (secureTags.length > 0) USAGE += secureTags[0].text(); USAGE += "\"},\n"; } } } try { BufferedReader in = new BufferedReader(new FileReader(source + path + name + ".skang")); String line; while ((line = in.readLine()) != null) DEFAULT += "\t\t\"" + escape(line, true) + "\",\n"; } catch (Exception e) {;} if ((SKANG.length() > 0) || (USAGE.length() > 0) || (DEFAULT.length() > 0)) { // Do an up to date check. try { File src = new File(source + path + name + ".java"); File dst = new File(dest + path + name + "Skanglet.java"); if (src.lastModified() < dst.lastModified()) continue; // with next class. } catch(Exception e) {;} int year = 1990; float version = (float) 0.0; if (COPYRIGHT.length() > 0) { int dotPos = COPYRIGHT.indexOf(' '); if (dotPos == -1) aRoot.printError(name + " : @.copyright not enough parameters - " + COPYRIGHT); else { String temp = COPYRIGHT.substring(0, dotPos); try { year = new Integer(temp).intValue(); if (1990 > year) throw(new Exception()); } catch (Exception e) {aRoot.printError(name + " : @.copyright invalid year - " + COPYRIGHT);} } } if (VERSION.length() > 0) { String temp[] = new String[4]; i = 0; int dotPos = 0; int lastPos = 0; while ((dotPos = VERSION.indexOf(' ', lastPos)) != -1) { temp[i++] = VERSION.substring(lastPos, dotPos); lastPos = dotPos + 1; } temp[i++] = VERSION.substring(lastPos); if (i != 4) aRoot.printError(name + " : @version not enough parameters - " + VERSION); try {version = new Float(temp[0]).floatValue();} catch (Exception e) {aRoot.printError(name + " : @version invalid number - " + VERSION);} // Should check VERSION type and date / time. } try { BufferedWriter out = new BufferedWriter(new FileWriter(dest + path + name + "Skanglet.java")); System.out.println(dest + path + name + "Skanglet.java"); out.write("// This file was automatically generated by the MakeSkanglet doclet.\n"); if (pack.length() > 0) out.write("package " + pack + ";\n"); out.write("import java.lang.String;\n"); out.write("public class " + name + "Skanglet extends net.matrix_rad.skang.SkangletBase\n"); out.write("{\n"); out.write("\tpublic " + name + "Skanglet()\n"); out.write("\t{\n\t\tsuper(MY_AUTHOR, MY_COPYRIGHT, " + year + ", MY_VERSION, " + version + ", MY_USAGE, MY_SKANG, MY_DEFAULT_SKANG);\n\t}\n\n"); out.write("\tpublic final static String MY_AUTHOR = \"" + AUTHOR + "\";\n"); out.write("\tpublic final static String MY_COPYRIGHT = \"" + COPYRIGHT + "\";\n"); out.write("\tpublic final static String MY_VERSION = \"" + VERSION + "\";\n"); out.write("\tpublic final static String MY_USAGE[][] = \n\t{\n"); out.write(USAGE); out.write("\t\t{" + "\"\", " + "\"\", " + "\"\", " + "\"\", " + "\"\", " + "\"\", " + "\"\", " + "\"\"}\n\t};\n"); out.write("\tpublic final static String MY_SKANG[][] = \n\t{\n"); out.write(SKANG); out.write("\t\t{" + "\"\", " + "\"\", " + "\"\", " + "\"\", " + "\"\", " + "\"\"}\n\t};\n"); out.write("\tpublic final static String MY_DEFAULT_SKANG[] = \n\t{\n"); out.write(DEFAULT); out.write("\t\t\"\"\n\t};\n"); out.write("}\n"); out.flush(); } catch (Exception e) {return false;} } } return true; } public static String escape(String aLine, boolean doSlashes) { int pos; // Escape everything in aLine that needs escaping. if (doSlashes) { pos = aLine .length(); while ((pos = aLine.lastIndexOf('\\', pos)) != -1) // Gotta do this one first! { aLine = aLine.substring(0, pos) + "\\" + aLine.substring(pos); pos--; } } pos = aLine .length(); while ((pos = aLine.lastIndexOf('"', pos)) != -1) aLine = aLine.substring(0, pos) + "\\" + aLine.substring(pos); return aLine; } }