import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.persistit.util.ArgParser;
public class SphinxDocPrep {
private final static Pattern PERSISTIT_PATTERN = Pattern
.compile("(``)?(com\\.persistit(?:\\.[a-z]\\w*)*(?:\\.[A-Z]\\w*)+)(?:#(\\w+(?:[\\(\\)\\,a-zA-Z]*)))?(``)?");
private final static String[] ARG_TEMPLATE = { "in|string:|Input file", "out|string:|Output file",
"index|string:|Pathname of index-all.html file", "base|string:|Base of generated URLs", };
enum BlockState {
OUT, WAIT_FIRST_BLANK_LINE, WAIT_SECOND_BLANK_LINE
}
private AsciiDocIndex index;
private BlockState block = BlockState.OUT;
private PrintWriter writer;
private String base;
private String indexPath;
private void prepare(final String[] args) throws Exception {
final ArgParser ap = new ArgParser("SphinxDocPrep", args, ARG_TEMPLATE);
final String inPath = ap.getStringValue("in");
final String outPath = ap.getStringValue("out");
writer = outPath.isEmpty() ? new PrintWriter(System.out) : new PrintWriter(new FileWriter(outPath));
base = ap.getStringValue("base");
if (base.isEmpty()) {
base = "http://akiban.com/persistit/doc/apidocs";
}
indexPath = ap.getStringValue("index");
if (indexPath.isEmpty()) {
indexPath = "/home/peter/website/apidocs/index-all.html";
}
index = new AsciiDocIndex();
System.out.print("Building JavaDoc index..");
index.buildIndex(indexPath, base);
System.out.println("done");
processFile(new File(inPath), 0);
writer.close();
}
public void processFile(final File file, final int level) throws Exception {
final BufferedReader reader = new BufferedReader(new FileReader(file));
System.out.print("Processing file " + file);
String line;
while ((line = reader.readLine()) != null) {
if (line.startsWith("@")) {
processFile(new File(file.getParentFile(), line.substring(1)), level + 1);
} else {
processLine(line);
}
}
writer.println();
System.out.println(" - done");
}
private void processLine(final String line) throws Exception {
if (line.contains("{{bug-list}}")) {
prepareBugList();
return;
} else if (line.contains(".. code-block:") || line.endsWith("::")) {
block = BlockState.WAIT_FIRST_BLANK_LINE;
} else if (line.isEmpty()) {
switch (block) {
case WAIT_FIRST_BLANK_LINE:
block = BlockState.WAIT_SECOND_BLANK_LINE;
break;
case WAIT_SECOND_BLANK_LINE:
block = BlockState.OUT;
break;
default:
// no change
}
}
if (block == BlockState.OUT) {
final StringBuffer sb = new StringBuffer();
if (line.startsWith("=")) {
sb.append("=");
}
final Matcher matcher = PERSISTIT_PATTERN.matcher(line);
while (matcher.find()) {
processMatch(matcher, sb);
}
matcher.appendTail(sb);
writer.println(sb.toString());
} else {
writer.println(line);
writer.flush();
}
}
private void processMatch(final Matcher matcher, final StringBuffer sb) {
final String className = matcher.group(2);
final String methodName = matcher.group(3);
String replacement;
if (methodName == null) {
final String url = index.getClassMap().get(className);
if (url == null || url.isEmpty()) {
replacement = "<<<Missing class: " + className + ">>>";
} else {
replacement = "`" + className + " <" + url + ">`_";
}
} else {
final String from = className + "#" + methodName.split("\\(")[0];
final SortedMap<String, String> map = index.getMethodMap().tailMap(from);
String url;
if (map.isEmpty()) {
replacement = "<<<Missing method: " + methodName + ">>>";
} else {
final String first = map.firstKey();
if (!first.startsWith(from)) {
replacement = "<<<Missing method: " + methodName + ">>>";
}
url = map.get(first);
url = url.replace(" ", "%20");
String text = first.split("#")[1];
if (!from.contains("(")) {
text = text.split("\\(")[0];
}
text = text.replace("com.persistit.encoding.", "");
text = text.replace("com.persistit.exception.", "");
text = text.replace("com.persistit.logging.", "");
text = text.replace("com.persistit.mxbeans.", "");
text = text.replace("com.persistit.ref.", "");
text = text.replace("com.persistit.ui.", "");
text = text.replace("com.persistit.", "");
text = text.replace("java.lang.", "");
text = text.replace("java.util.", "");
replacement = "`" + text + " <" + url + ">`_";
}
}
matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
}
private void prepareBugList() throws IOException {
final List<String[]> rows = new ArrayList<String[]>();
rows.add(new String[] { "Bug Reference", "Fixed in|Version", "Summary" });
BufferedReader reader = null;
try {
String urls = "";
String version = "";
reader = new BufferedReader(new FileReader("../BugList"));
final StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
if (line.isEmpty()) {
if (sb.length() > 0) {
sb.append('|');
}
} else if (Character.isDigit(line.charAt(0))) {
if (!urls.isEmpty()) {
rows.add(new String[] { urls, version, sb.toString() });
urls = "";
version = "";
sb.setLength(0);
}
final String[] split = line.split("\\:");
for (final String bug : split[0].trim().split(",")) {
if (urls.length() > 0) {
urls += '|';
}
urls = urls + "https://launchpad.net/bugs/" + bug;
}
version = split[1].trim();
} else {
sb.append(line.trim());
if (sb.length() > 0) {
sb.append('|');
}
}
}
if (!urls.isEmpty()) {
rows.add(new String[] { urls, version, sb.toString() });
}
final int[] maxWidth = new int[3];
for (final String[] row : rows) {
for (int i = 0; i < 3; i++) {
for (final String s : row[i].split("\\|")) {
maxWidth[i] = Math.max(s.length(), maxWidth[i]);
}
}
}
bugTableLine(sb, false, maxWidth);
for (int l = 0;; l++) {
if (bugTableText(sb, rows.get(0), maxWidth, l)) {
break;
}
}
bugTableLine(sb, true, maxWidth);
for (int i = 1; i < rows.size(); i++) {
final String[] text = rows.get(i);
for (int l = 0;; l++) {
if (bugTableText(sb, text, maxWidth, l)) {
break;
}
}
bugTableLine(sb, false, maxWidth);
}
} catch (final IOException e) {
System.out.println(e + " while trying to read BugList");
} finally {
if (reader != null) {
reader.close();
}
}
}
private void bugTableLine(final StringBuilder sb, final boolean dline, final int[] width) {
sb.setLength(0);
sb.append('+');
for (int j = 0; j < 3; j++) {
for (int i = 0; i < width[j] + 2; i++) {
sb.append(dline ? '=' : '-');
}
sb.append('+');
}
writer.println(sb);
writer.flush();
}
private boolean bugTableText(final StringBuilder sb, final String[] text, final int[] width, final int line) {
final String[] s = new String[3];
boolean done = true;
for (int j = 0; j < 3; j++) {
final String[] split = text[j].split("\\|");
if (split.length > line) {
done = false;
s[j] = split[line];
}
}
if (!done) {
sb.setLength(0);
sb.append("|");
for (int j = 0; j < 3; j++) {
if (s[j] == null) {
s[j] = "";
}
sb.append(' ');
sb.append(s[j]);
for (int i = s[j].length() + 1; i < width[j] + 2; i++) {
sb.append(' ');
}
sb.append('|');
}
writer.println(sb);
}
writer.flush();
return done;
}
public static void main(final String[] args) throws Exception {
new SphinxDocPrep().prepare(args);
}
}