HTML Document Generation


JavaDoc is useful documentation, but insufficient to give potential users how a tool or package is to be used.  HTML is a standard medium and language for doing this. And in such documentation, code examples and their inputs and outputs should be given to illustrate key ideas and idiomatic usage. Writing such documentation is hard enough -- but keeping the examples up-to-date with ongoing package updates and refactorings without tool support is close to impossible.

HTML documentation for MDELite was produced by a document generator -- a simple Java class that extracts code examples + input/output files from regression tests and inserts them at designated locations into HTML templates to yield up-to-date documentation.  The entire process of document generation is part of MDELite regression tests, which not only runs the afore-mentioned regression tests, it also generates the HTML output.

The file MDELite.DocumentGenerator offers a single static method to accomplish this:
void main( Source sourceCodeFile, String htmlTemplateFile, String htmlOutputFile )
where:
Table of Contents
Examples of DocumentGeneration can be found in the MDELite Netbeans Project in files: test/DML/Prolog/Doc*.java.

Source Java Code File Format

Regression tests are Java files.  A code example in such a file looks like:
@Test
public void toTableTest() {
RegTest.Utility.redirectStdOut(errorfile);
toTable();
RegTest.Utility.validate(errorfile, correct + "toTable.txt", false);
}

///toTable
void toTable() {
DB db = DB.read(testdata + "dogOwner.do.pl");
Table dog = db.getTableEH("dog");

// Step 1: stream dog, and collect into a new dog table
Table dog2 = dog.stream().collect(new TuplesToTable());
boolean result = dog2.equals(dog);
System.out.format("dog2 %s dog", result ? "=" : "!=");
}
///toTable

The JUnit regression test is indicated by the @Test annotation.  The code example is inbetween the ///toTable markers, where the example is named "toTable".  The DocumentGenerator reads a JUnit test file and harvests the text of examples and stores them by their name.


HTM Template File

An HTM template file ends in ".htm".  It is a standard HTML file with the followning exceptions:

---toTable---

:::DocGen/Figures/fileHole.txt::: 
That's it.  The purpose of the template file is to provide text to explain examples and illustrate input and outputs (files) to these examples.


HTML Output File

As said above, the Template file with its holes are read in.  So too is a single Java regression test with examples.  The DocumentGenerator fills these "holes" with named code examples that it harvested and the contents of files that it read.  The resulting text is written to the "html output file".


Usage

The typical usage of DocumentGenerator is a single call, written as JUnit test (so when regression tests are run, up-to-date documentation is produced):
@Test
public void families() {
main("src/LectureExamples/FamiliesM2M.java", "DocGen/FamiliesDemo.htm", "Docs/FamiliesDemo.html");
}
Sometimes code examples are taken from several Java regression tests.  In such cases, html output files are placed in a directory that ultimately will be deleted, such as this example where a template file requires code examples from three different sources:
@Test
public void allegories() {
main("src/LectureExamples/allegory/Main.java", "DocGen/AllegoryDemo.htm", "DELETE.htm");
main("src/LectureExamples/allegory/PDD.java", "DELETE.htm", "DELETE1.htm");
main("test/LectureExamples/Correct/x.PDD.pl", "DELETE1.htm", "Docs/AllegoryDemo.html");
}
Here's another idiom: A tool is invoked to produce a file whose output is to be inserted into an HTMLOutputFile.
void yumlSetup() {
Yuml.ClassParser.main("test/BuildDocumentation/Test/x.yuml.yuml", "outYuml1.txt");
Yuml.ClassParser.main("test/BuildDocumentation/Test/y.yuml.yuml", "outYuml2.txt");
}

@Test
public void yuml() {
yumlSetup();
main("test/BuildDocumentation/test/nothing.jav", "DocGen/YumlManualTemplate.htm", "Docs/YumlManual.html");
}
The method yumlSetup() calls the Yuml.ClassParser to parse two different files (x.yuml.yuml and y.yuml.yuml) into separate output files. These files are then read by the YumlManualTemplate.htm template file to fill "file holes".  Interestingly, in this case, there is no Java regression test from which to harvest code examples -- that is, the template file contains holes only for files.  So a "nothing.jav" file -- literally an empty file -- is given as the Java file to harvest.

JUnit Test Structure

Nothing fancy is needed.  You should have a JUnit setUpClass()  method to create a generated "Docs" directory in red below (which you should delete prior to running regression tests as part of ANT makefiles).  Then you should have a series of HTML file generation tests in purple below, terminating with the creation of an index.html file from a template that, in this case, has no code or file holes to fill:

public class BuildDocTest extends DocumentGenerator {

@BeforeClass
public static void setUpClass() {
new File("Docs").mkdir();
}

@Test
public void m2m() {
main("test/DML/PrologDB/DocExamplesTest.java", "DocGen/M2MTemplate.htm", "Docs/M2MPrograms.html");
}

...

@Test
public void index() throws Exception {
main("test/BuildDocumentation/test/nothing.jav", "DocGen/indexTemplate.htm", "Docs/index.html");
}
Note: if a hole cannot be filled, either because there is no code example with the given name or that the file referenced does not exist, the marker of the code example or file will remain unchanged.