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;
}
}