Creating good software documentation for other software developers can be a challenging task. Writing valid documentation, with tested source code examples, is even more difficult. Traditionally, there were no tools which could guarantee the validity of the documented source code examples.
Imagine that you have to document your software, and that you want to write a tutorial that explains
how to use the software step-by-step. First you'd usually write some example code, like
a HelloWorld.java class that can actually be executed. Hence, you
validate your example code by running it. Maybe you even write some unit tests when your
tutorial application is more complex. Next you switch into documentation mode and start
writing your tutorial. You start copying and pasting the code from your IDE into your text processor.
You then realize that you can no longer test it, or make changes to it and ensure that it still works,
because your documentation tools do not support this.
Instead of switching between your IDE and your text processor, you could write the example code and your tutorial text in your IDE. After all, it's your favorite text editor anyway. But it doesn't support WYSIWYG, so you have to write text in some markup language, like HTML or XML. And although you avoid switching between two different applications, your writing process still involves copying and pasting of code from testable classes into documentation markup source files. You'll probably find refactoring a little easier, but it's not really much better than having two different environments.
Lemma bridges that gap. It helps you avoid copying and pasting code into documentation; it inserts code snippets (and other elements) into your tutorial text automatically. This is a citation mechanism that allows you to only maintain one copy of source code, and have it validated, tested, and documented all at the same time.
Let's assume you want to test and document the following HelloWorld Java class:
package example.helloworld;
/**
* Just print a hello.
* <p>
* This class doesn't do much, its only purpose is to print a
* message to <code>System.out</code> without any fuzz.
* </p>
*/
public class HelloWorld {
/**
* Prints "Hello World".
*/
public void sayHello() {
System.out.println(getMessage());
}
public String getMessage() {
return "Hello World!";
}
}
First, write a unit test method that checks the class:
@Test
public void testHelloWorld() {
HelloWorld hw = new HelloWorld();
assert hw.getMessage().equals("Hello World!");
assert hw.getMessage().endsWith("!");
hw.sayHello();
}
This unit test not only validates the correct behavior of the class, it also shows how the class is
supposed to be used. Traditionally, you'd now add a section in your software's manual, where you copy and
paste the code of the HelloWorld class and some lines from the unit test. Your users will
then be able to understand the internals and how they should work with the class.
With Lemma you don't copy/paste anything but write documentation as Javadoc on the test method in XHTML syntax:
/**
* The {@code HelloWorld} class
* <p>
* This is the source of the class:
* </p>
*
* <a class="citation"
href="javacode://example.helloworld.HelloWorld"/>
*
* <p>
* To use the class, first instantiate it, then call either {@code getMessage()} to retrieve
* the message string or {@code sayHello()} to print the message to {@code System.out}:
* </p>
*
* <a class="citation"
href="javacode://example.helloworld.HelloWorldTest#testHelloWorld"
style="include: HELLOWORLD_USAGE;"/>
*
* <p>
* If you don't want the message printed to {@code System.out}, don't call the
* {@code sayHello()} method.
* </p>
*/
@Test
public void testHelloWorld() {
HelloWorld hw = new HelloWorld(); // DOC: HELLOWORLD_USAGE
assert hw.getMessage().equals("Hello World!");
assert hw.getMessage().endsWith("!");
hw.sayHello(); // DOC: HELLOWORLD_USAGE
}
You probably already know all of the XHTML elements and attributes used in this Javadoc comment, in fact, you can use any tags you need to write your documentation.
Lemma parses your markup and replaces the content of
<a> elements that have a citation class. The first anchor in the example above is
referencing the raw Java source code of a class called example.helloworld.HelloWorld. How this source
code is found by Lemma depends on your configuration, we'll look at that later. Note how the URL scheme
javacode:// is used to indicate what part of the referenced resource you want to cite. This URL is actually
refactoring-safe, your IDE should be able to automatically update the URL string when you rename the package or
HelloWorld class name.
The second anchor is more specific, it's a citation for a fragment of code. The URL references the source of the
test class and the test method (yes, it's referencing "itself"). You'll probably recognize the method reference syntax
from Javadoc, it's the same as for regular Javadoc @link and @see tags, hence also safe for
refactoring. Citation options are declared with the style attribute, they look like CSS options. The
include option shown here accepts a list of fragment labels which should be cited. A fragment label is
a Java line comment starting with "// DOC: (LABEL)". Two lines with the same label mark the beginning and end
of a fragment block. So this citation will only include the four lines of the method body. You'll later see more
details about citation options, fragments, and labels.
The previous Javadoc represents just one small section of your overall documentation. Lemma's default processing pipeline expects that you also create a master template file in XHTML that brings together all of your documentation parts, chapters, and sections. How that template looks like, and how parts, chapters, and sections are organized and finally rendered is up to you. Here is a simple example of a template:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My Manual</title>
<style type="text/css">
.chapter .title {
font-size: 110%;
font-weight: bold;
}
.file .content, .javacode .content {
font-family: monospace;
white-space: pre;
margin: 15px;
padding: 5px;
border: 1px solid #aaaaaa;
background-color: #f0f0f0;
}
</style>
</head>
<body>
<div class="frontmatter">
<h1>This is my manual</h1>
</div>
<div class="chapter">
<a class="citation"
href="javadoc://example.helloworld.HelloWorldTest#testHelloWorld()"/>
</div>
</body>
</html>
Note that the URL scheme for this citation is javadoc://. The Lemma processor will follow the URL
to your test class and test method, and then read and process the Javadoc comment of that resource. This is a recursive
procedure, so any citation anchors in the Javadoc comment are followed and processed as well. Finally, the following output
is generated:
<?xml version="1.0" encoding="utf-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My Manual</title>
<style xml:space="preserve" type="text/css">
.chapter .title {
font-size: 110%;
font-weight: bold;
}
.file .content, .javacode .content {
font-family: monospace;
white-space: pre;
margin: 15px;
padding: 5px;
border: 1px solid #aaaaaa;
background-color: #f0f0f0;
}
</style>
</head>
<body>
<div class="frontmatter">
<h1>This is my manual</h1>
</div>
<div class="chapter">
<div class="citation javadoc" id="javadoc.example.helloworld.HelloWorldTest.testHelloWorld..">
<div class="title">The <code><![CDATA[HelloWorld]]></code> class</div>
<div class="content">
<p>
This is the source of the class:
</p>
<div class="citation javacode" id="javacode.example.helloworld.HelloWorld">
<div class="content">
<pre class="prettyprint">package example.helloworld;
/**
* Just print a hello.
* <p>
* This class doesn't do much, its only purpose is to print a
* message to <code>System.out</code> without any fuzz.
* </p>
*/
public class HelloWorld {
/**
* Prints "Hello World".
*/
public void sayHello() {
System.out.println(getMessage());
}
public String getMessage() {
return "Hello World!";
}
}
</pre>
</div>
</div>
<p>
To use the class, first instantiate it, then call either <code><![CDATA[getMessage()]]></code> to retrieve
the message string or <code><![CDATA[sayHello()]]></code> to print the message to <code><![CDATA[System.out]]></code>:
</p>
<div class="citation javacode" id="javacode.example.helloworld.HelloWorldTest.testHelloWorld..">
<div class="content">
<pre class="prettyprint">HelloWorld hw = new HelloWorld();
assert hw.getMessage().equals("Hello World!");
assert hw.getMessage().endsWith("!");
hw.sayHello();
</pre>
</div>
</div>
<p>
If you don't want the message printed to <code><![CDATA[System.out]]></code>, don't call the
<code><![CDATA[sayHello()]]></code> method.
</p>
</div>
</div>
</div>
</body>
</html>
The formatting and indentation of this XHTML document has been automatically generated by a pretty printer, so it readability could obvioulsy be improved. All Javadoc code fragments have been properly escaped in CDATA sections. All cited source fragments have been escaped with XHTML entities instead (future versions of Lemma will likely embed XHTML markup for callouts into code blocks, hence they are not defined as CDATA sections).
This is how it looks rendered in a browser:

Lemma can be integrated in any Java project: You can call it from your command-line as a standalone JAR file, or you can integrate it with your Maven build.
The Lemma distribution ships with a standalone JAR file which you can execute directly:
$ java -jar lemma-core-*-standalone.jar Option "-d" is required USAGE: java -jar <JARFILE> [options] -d <path> : The base path of all source and resource files. -i <template.xhtml> : XHTML template file. -o <result.xhtml> : XHTML output file. -overwrite true|false : Overwrite existing output file quietly. -p <package.name> : Included package, repeat option for multiple packages.
You can already see that Lemma requires you to specify a base path under which it can
find all your sources (and resources such as documentation pictures). This is typically
your unit test source directory. Lemma will parse and read your Java unit test source
files - note that this is NOT your unit test compile output directory but
really the directory under which all your MyUnitTest.java files are stored.
The -i <template.xhtml> option is also required, use it to specify
your "master" documentation template. This XHTML file is the entry point of your documentation;
it is where your first citation anchor will link into the rest of your unit tests.
Finally, you have to provide the name of an output file. Lemma, in standalone mode, will only
write this file and nothing else (no other resources will be generated or copied). Lemma
will ask if you really want to overwrite this output file if it already exists, unless you
call it with -overwrite true.
Let's assume that your project has the following structure (omitting the main source files):
/myproject
`-- src
|-- manual
| `-- myproject-manual.xhtml
`-- test
`-- java
`-- com
`-- myproject
`-- HelloWorld.java
If you want the manual output file generated in target/manual/myproject-manual.xhtml, call Lemma
as follows:
/myproject/$ java -jar lemma-core-*-standalone.jar \ -d src/test/java \ -i src/manual/myproject-manual.xhtml \ -o target/manual/myproject-manual.xhtml
The src/manual/myproject-manual.xhtml file looks as follows:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My Manual</title>
</head>
<body>
<div>
<a class="citation" href="javadoc://com.myproject.HelloWorld"/>
</div>
</body>
</html>
And the HelloWorld.java class is this:
package com.myproject;
/**
* Just print a hello.
* <p>
* This class doesn't do much, its only purpose is to print a
* message to <code>System.out</code> without any fuzz.
* </p>
*/
public class HelloWorld {
/**
* Prints "Hello World".
*/
public void sayHello() {
System.out.println(getMessage());
}
public String getMessage() {
return "Hello World!";
}
}
After running Lemma, you'll have generated an XHTML output file with the Javadoc of
the HelloWorld class cited in your template.
Note that Lemma, if started from the command-line as shown here, only generates the
XHTML output file. It does not copy any of your resources such as doc-files
contents (used in Javadoc) or other files (such as CSS) from your manual source folder
into the target directory. You will have to copy these by hand or use the Lemma plugin
for a Maven build of your project.
Lemma relies on the Javadoc tool for documentation parsing. The Javadoc tool is quite old and rather crude. Don't worry, Lemma will hide much of its complexity. Even so, you will most likely encounter certain log messages and warnings related to packages and classes, which you can ignore most of the time. Read on to find out what these messages are and why they occur. You can skip this section if you trust Lemma to do the right thing - and if you have the ability to ignore potentially thousands of warning messages.
The Javadoc tool reads both source and class files (using the classpath) to build its internal index. When Lemma starts (and if you followed the steps in the previous section) you should see the following line on your console:
Included package: com.myproject
This means that Lemma now understands any references to and from classes of that package and its sub-packages. By default, Lemma will look into the given base path directory (where your unit tests are), and configure the Javadoc tool internally with the first-level sub-directories as package names.
The only subdirectory in the previous example was com, as in
myproject/src/test/java/com. The log message is printed by the Javadoc tool, which
after being told by Lemma to consider "com", found the com.myproject
package in your source folder. It will now proceed to read the source files in that
folder to build its index.
However, it won't stop there. The Javadoc index will also include any compiled classes within
the com.myproject package - if they are available on the classpath. If you started
Lemma from the command-line without any additional classpath elements, no additional classes
and sub-packages of com.myproject will be available, hence, the Javadoc index
will only contain your test classes.
Let's assume that your unit test references a class that is not part of your tests but of your
main codebase - a likely scenario. The following class in
src/test/java/com/myproject/ references the com.myproject.Foo class which is
not located in the test sources:
package com.myproject;
public class FooTest {
public Foo getFoo() {
return new Foo();
}
}
You will see a rather frighenting message on startup:
/myproject/src/test/java/com/myproject/FooTest.java:5: cannot find symbol
symbol : class Foo
location: class com.myproject.FooTest
public Foo getFoo() {
^
If this would be a regular run of the Java compiler, it would have been aborted. As it is, this is
just how the Javadoc tool let's you know that it could not add Foo to its index. It was
not in your test source path and not in compiled form on your classpath. Lemma
will continue to execute and probably complete the manual build as expected. To satisfy the Javadoc
tool and hide the message, you should consider adding your compile output path to the classpath
(and calling Lemma after compiling your main sources into that output path). The following configuration
assumes that Foo.class is present in target/classes/my/project/:
/myproject/$ java -Denv.class.path=target/classes/ -jar lemma-core-*-standalone.jar \ -d src/test/java \ -i src/manual/MyManualTemplate.xhtml \ -o target/manual/MyManual.xhtml
You can NOT use the regular java -cp [xxx] option to specify the classpath on
the command-line, the Javadoc tool (like the javac compiler) uses a system property to configure
its classpath.
Note again that the missing-symbol message is just an informational message which looks more important than it is - unfortunately Lemma can't separate and hide these messages from other, more severe error messages.
Another warning message you might now frequently see is the following:
[WARNING] EasyDoclet Application: warning - No source files for package com.myproject.bar [WARNING] EasyDoclet Application: warning - No source files for package com.myproject.baz
This warning let's you know that although Lemma added all classes and sub-packages of
com.myproject.* to the internal Javadoc index, some of the packages that were found
on the classpath are only available in compiled form (on the classpath) and not in source form in
your base (unit test) directory.
You can restrict the "known" packages and the citation scope that Lemma understands by
specifying the -p <package.name> option once or several times. If you
do not care about the warnings - and note again that this message is really a "feature" of the
Javadoc tool - you do not have to provide any package names.
If your project already relies on Maven as a build system, Lemma can be integrated in a few minutes. This guide assumes that you are using the Maven default locations for sources, unit test sources, build target output, and so on.
First, add the Teleal repository to your pom.xml:
<pluginRepositories>
<pluginRepository>
<id>teleal.org-repo</id>
<url>http://teleal.org/m2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
You can call the Lemma plugin for Maven directly, without any additional configuration:
/myprojects/$ mvn clean org.teleal.lemma:lemma-maven-plugin:manual
This execution will look for an XHTML template file in src/manual/myproject-manual.xhtml
and generate the output XHTML file in target/manual/myproject-manual.xhtml. You might
however get "cannot find symbol" warning messages on your console - see the previous section for
a more detailed explanation why these occur. To prevent these messages, call the compile
and test-compile lifecycles before you execute the Lemma manual
plugin goal. The plugin will automatically add your compiled classes and test-classes to the Javadoc
classpath:
/myprojects/$ mvn clean compile test-compile org.teleal.lemma:lemma-maven-plugin:manual
The Lemma plugin will also copy additional documentation resources into your manual target directory.
From your manual source folder, all files and sub-directories will be copied as they are. You can store
additional resources there and reference them in your main XHTML template (CSS and Javascript files
in particular). Note that any files that are named *.xhtml are not copied from your
manual source folder - Lemma assumes that all XHTML files are part of the manual compilation.
Furthermore, all files from your Java source (unit tests) directory are copied if they are stored
in doc-files directories. These special directories are part of the Javadoc system, as
explained here. You
should store images and other resources there which you'd like to reference from within Javadoc
comments. All files from all found directories will be copied flat, that is, the package structure
will not be preserved but all doc-files/* from all source packages will end up in a single
target manual/doc-files/ directory. This makes rewriting of references unecessary, and
you'll be warned when a duplicate filename is detected.
You can of course execute the documentation build proccess in your project's package lifecycle,
add to your pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.teleal.lemma</groupId>
<artifactId>lemma-maven-plugin</artifactId>
<version>1.0</version> <!-- Make sure you use the latest version! -->
<executions>
<execution>
<id>package-manual</id>
<phase>prepare-package</phase>
<goals>
<goal>manual</goal>
</goals>
</execution>
</executions>
<configuration>
<packageNames> <!-- This is optional, see previous section -->
<packageName>com.myproject</packageName>
</packageNames>
</configuration>
</plugin>
...
A more complex example which overrides many of the default settings:
<build>
<plugins>
<plugin>
<groupId>org.teleal.lemma</groupId>
<artifactId>lemma-maven-plugin</artifactId>
<version>1.0</version> <!-- Make sure you use the latest version! -->
<executions>
<execution>
<id>package-manual</id>
<phase>prepare-package</phase>
<goals>
<goal>manual</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- The directory containing your manual template and
resources, defaults to "${basedir}/src/manual". -->
<manualSourceDirectory>${basedir}src/mydocs/</manualSourceDirectory>
<!-- The name of the input XHTML template file in the manual source
directory, defaults to "${project.artifactId}-manual.xhtml". -->
<templateFilename>MyManual.xhtml</templateFilename>
<!-- The name of the output directory within the build (target) directory,
defaults to "manual". -->
<outputPath>mydocs</outputPath>
<!-- The name of the output XHTML file without suffix, defaults
to "${project.artifactId}-manual". -->
<outputFilename>MyManual</outputFilename>
<!-- Optional package names to restrict the Lemma/Javadoc scope. -->
<packageNames>
<packageName>com.myproject</packageName>
<packageName>com.somepkg</packageName>
</packageNames>
</configuration>
</plugin>
...
You can also integrate the Lemma plugin for generation of website documentation. TODO: Document this.
A citation anchor is an <a class="citation"/> element which in its href attribute references
the resource that should be cited. Lemma processes citation anchors and replaces the anchor element with
fragments of Javadoc comments or Java source - in fact, it can include content from any citation resource
which
has a matching reader.
The following table shows URI schemes, which enable a particular reader, and the resource types the citation content will be extracted from:
| URI scheme | Examples | Description |
|---|---|---|
javadoc | <a ... href="javadoc://my.package"/>
<a ... href="javadoc://my.package.MyClass"/>
<a ... href="javadoc://my.package.MyClass.MyNestedClass"/>
<a ... href="javadoc://my.package.MyClass#myMethod"/>
<a ... href="javadoc://my.package.MyClass#myMethod()"/>
<a ... href="javadoc://my.package.MyClass#otherMethod(Type, Type)"/>
<a ... href="javadoc://this"/> | Include the Javadoc XHTML (well-formed) comment text of the specified package, class, or method, after recursively processing any citation anchors found in the markup. |
javacode | <a ... href="javacode://my.package"/>
<a ... href="javacode://my.package.MyClass"/>
<a ... href="javacode://my.package.MyClass.MyNestedClass"/>
<a ... href="javacode://my.package.MyClass#myMethod"/>
<a ... href="javacode://my.package.MyClass#myMethod()"/>
<a ... href="javacode://my.package.MyClass#otherMethod(Type, Type)"/>
<a ... href="javacode://this"/> | Include the raw source code of the referenced package, class, or method. Note that method source code includes Java annotations but not the Javadoc comment source of the method. |
file | <a ... href="file://my/directory/path/to/any/file.xml"/>)
<a ... href="file://my/directory/path/to/otherfile.csv"/>)
<a ... href="file://my/directory/path/morecontent.xhtml"/>)
<a ... href="file://my/package/MyClass.java"/>)
<a ... href="my/directory/path/somefile.txt"/>) |
Include the contents of the referenced file, selecting a matching reader based on the file
extension.
Note that if no URL is specified in a citation anchor (see last example), a reader is selected based
on file
extension. Hence, the file:// prefix is actually not necessary.
|
Although URLs which reference the fully qualified name of a class, method, or package are
safe for refactoring in a good IDE, an equally safe shorthand is available with the
special path "this." For example, the following Javadoc will contain a
citation from the method it is written on:
/**
* Calling Hello World
* <p>
* A anchor which cites this method's code:
* </p>
* <a class="citation" href="javacode://this"/>
*/
public void callHelloWorld() {
new HelloWorld();
}
You can use this shorthand for any citation anchor in Javadoc on classes, methods, and packages. If your citation anchor is within the Javadoc comment of a class, 'this' followed by a fragment references a method of the class:
/**
* This is My Class
* <p>
* And this is a citation anchor which references the source
* of a method of this class:
* </p>
* <a class="citation" href="javacode://this#myMethod"/>
*/
public static class MyClass {
public void myMethod() {
System.out.println("Hello World!");
}
}
Citation can be customized with options, specified as CSS-like values with the {@code style} attribute of the anchor element.
When Lemma reads your Javadoc comment, it will use the "first sentence" (as defined by Javadoc) of the
comment as the title of the citation section. For example, the HelloWorld class shown previously
has the first sentence title "Just print a hello.". Lemma will remove the period at the end of the first
sentence automatically. You can disable this behavior with the read-title option:
<a class="citation" href="javadoc://example.helloworld.HelloWorld" style="read-title: false"/>
Your Javadoc comment is now cited as it is, with no special treatment of the "first sentence". Alternatively,
you can use the title attribute of the anchor to override any "first sentence" title:
<a class="citation" href="javadoc://example.helloworld.HelloWorld" title="My Custom Title"/>
A javacode:// citation which references a Java package, class, or method, will by default
include all lines of code of that package, class, or method. Very often you only want a fragment of the
code lines cited. First, you have to declare the fragments with line comments in your Java source file:
package example.helloworld;
/**
* Just print a hello.
* <p>
* This class doesn't do much, its only purpose is to print a
* message to <code>System.out</code> without any fuzz.
* </p>
*/
public class HelloWorld {
// DOC:FRAGMENT1
/**
* Prints "Hello World".
*/
public void sayHello() {
System.out.println(getMessage());
}
// DOC:FRAGMENT1
public String getMessage() { // DOC: FRAGMENT2
return "Hello World!"; // DOC: FRAGMENT3
} // DOC: FRAGMENT2
}
Within this Java source file, three fragments have been declared. The first two fragment are multi-line block
fragments, the third is a single-line fragment. The rules are: A line comment starting with a // DOC: prefix marks
the beginning of a fragment. The DOC: prefix is followed by a fragment label, which has to
match the following regular expression: [A-Z_-]+[0-9]* If the label is not repeated in a subsequent
line, the fragment only includes a single line. If the label is repeated in a subsequent line, all lines in
between and including the labeled lines are considered part of the same multi-line fragment block. A fragment
label comment can be placed in an empty line or at the end of a line, after content you wish to include in
the fragment.
You can now use the labeled fragments to selectively include and/or exclude content in citations:
<a class="citation" href="javacode://example.helloworld.HelloWorld" style="include: FRAGMENT1, FRAGMENT2"/>
This citation only includes the two named fragments, producing the following output:
<div class="citation javacode" id="javacode.example.helloworld.HelloWorld">
<div class="content">
<pre class="prettyprint">
/**
* Prints "Hello World".
*/
public void sayHello() {
System.out.println(getMessage());
}
public String getMessage() {
return "Hello World!";
}
</pre>
</div>
</div>
Exclusion of fragments occurs after inclusion, as the following example demonstrates:
<a class="citation" href="javacode://example.helloworld.HelloWorld" style="include: FRAGMENT1, FRAGMENT2; exclude: FRAGMENT3"/>
The excluded fragment is now missing from the output:
<div class="citation javacode" id="javacode.example.helloworld.HelloWorld">
<div class="content">
<pre class="prettyprint">
/**
* Prints "Hello World".
*/
public void sayHello() {
System.out.println(getMessage());
}
public String getMessage() {
}
</pre>
</div>
</div>
Lemma will automatically remove any fragment labels - the specially formatted comments - from cited
content. It is sometimes useful, for example to document the actual usage of Lemma, to keep the
fragment labels in a piece of cited source code. For example, given the same HelloWorld class marked
with three fragments from the previous example, the following citation would preserve the labels:
<a class="citation" href="javacode://example.helloworld.HelloWorld" style="include: FRAGMENT2; clean-labels: false;"/>
This produces the following output:
<div class="citation javacode" id="javacode.example.helloworld.HelloWorld">
<div class="content">
<pre class="prettyprint">public String getMessage() { // DOC: FRAGMENT2
return "Hello World!"; // DOC: FRAGMENT3
} // DOC: FRAGMENT2
</pre>
</div>
</div>
As a special case, you can also preserve only the fragment labels within a fragment block, and still remove the labels that defined the actual fragment block:
<a class="citation" href="javacode://example.helloworld.HelloWorld" style="include: FRAGMENT2; clean-labels: boundary;"/>
<div class="citation javacode" id="javacode.example.helloworld.HelloWorld">
<div class="content">
<pre class="prettyprint">public String getMessage() {
return "Hello World!"; // DOC: FRAGMENT3
}
</pre>
</div>
</div>
You have seen in previous chapters how to cite documentation and source fragments using
the javadoc:// and the javacode:// URI schemes. The third URI
scheme supported by Lemma, file://, enables citation from any source, not just
Java code.
A citation with the file:// scheme will select a matching citation source reader
based on the file you are referencing, and the file name extension.
Let's assume you have an XML file - note that its schema or DTD does not matter because Lemma will never try to actually parse it as XML. You want to include some lines of this XML file, or the whole file content in your documentation:
<orders>
<!-- DOC:ORDER1 -->
<order id="1">
<lineitem product-id="123" quantity="1" item-price="99.90"/>
<lineitem product-id="456" quantity="2" item-price="12.29"/>
<lineitem product-id="888" quantity="1" item-price="1.99"/>
</order>
<!-- DOC:ORDER1 -->
<order id="2">
<lineitem product-id="777" quantity="2" item-price="10.00"/>
</order>
</orders>
In your manual template (or any Javadoc comment), create a citation anchor referencing this file:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My Orders</title>
</head>
<body>
<div>
<a class="citation"
href="file://example/citexml/MyOrders.xml"/>
</div>
</body>
</html>
Lemma will generate the following output:
<?xml version="1.0" encoding="utf-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My Orders</title>
</head>
<body>
<div>
<div class="citation file" id="file.example_citexml_MyOrders.xml">
<div class="content">
<pre class="prettyprint"><orders>
<order id="1">
<lineitem product-id="123" quantity="1" item-price="99.90"/>
<lineitem product-id="456" quantity="2" item-price="12.29"/>
<lineitem product-id="888" quantity="1" item-price="1.99"/>
</order>
<order id="2">
<lineitem product-id="777" quantity="2" item-price="10.00"/>
</order>
</orders>
</pre>
</div>
</div>
</div>
</body>
</html>
Just like with Javadoc comments or code, you can use citation options to customize the included content:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My Orders</title>
</head>
<body>
<div>
<a class="citation"
href="file://example/citexml/MyOrders.xml" style="include: ORDER1"/>
</div>
</body>
</html>
The output now only contains the source of the given fragment(s):
<?xml version="1.0" encoding="utf-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My Orders</title>
</head>
<body>
<div>
<div class="citation file" id="file.example_citexml_MyOrders.xml">
<div class="content">
<pre class="prettyprint"><order id="1">
<lineitem product-id="123" quantity="1" item-price="99.90"/>
<lineitem product-id="456" quantity="2" item-price="12.29"/>
<lineitem product-id="888" quantity="1" item-price="1.99"/>
</order>
</pre>
</div>
</div>
</div>
</body>
</html>
Regular text files that end with a .txt or .csv extension use the #
character as a comment marker:
(orders
# DOC:ORDER1
(order id=1
(lineitem product-id=123, quantity=1, item-price=99.90)
(lineitem product-id=456, quantity=2, item-price=12.29)
(lineitem product-id=888, quantity=1, item-price=1.99)
)
# DOC:ORDER1
(order id=2
(lineitem product-id=777, quantity=2, item-price=10.00)
)
)
Reference the file in your citation anchor, and if required any inclusion labels:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My Orders</title>
</head>
<body>
<div>
<a class="citation"
href="file://example/citeplaintext/myorders.txt" style="include: ORDER1"/>
</div>
</body>
</html>
Lemma will generate the following output:
<?xml version="1.0" encoding="utf-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My Orders</title>
</head>
<body>
<div>
<div class="citation file" id="file.example_citeplaintext_myorders.txt">
<div class="content">
<pre>(order id=1
(lineitem product-id=123, quantity=1, item-price=99.90)
(lineitem product-id=456, quantity=2, item-price=12.29)
(lineitem product-id=888, quantity=1, item-price=1.99)
)
</pre>
</div>
</div>
</div>
</body>
</html>
Lemma does not restrict how you write your documentation, that is, it does not mandate any particular subset of XHTML elements you have to use exclusively. Any XHTML element that is within the XHTML 1.1 specification is good. On the other hand, as this chapter will show, there are some best practices you should be aware of.
Also, certain features of XML itself such as XInclude are not used frequently by most developers but can play an important role in Lemma when your documentation grows beyond a few simple Javadoc comments.
Sometimes you do not want to cite Java or XML code, you want to write it by hand. The same rules as usual apply: Your code is going to be included in an XHTML document and it therefore has to be escaped and encoded properly.
In XML you can either escape a whole a block from parsing by marking it as CDATA,
or you can encode all "<" and ">" characters using < and
> XML entities . Also, but note that this is optional, you should wrap
your code in <code> or <pre> elements to control the
rendering in monospaced font, and to preserve newlines in code blocks.
The following example shows a Java code block and an inline code fragment within an XHTML document:
<p>
This is the <code>HelloWorld</code> class which prints
a <code><hello></code> element:
</p>
<div><pre><![CDATA[
public class HelloWorld {
public String print() {
return "<hello>world</hello>";
}
}
]]></pre></div>
It is usually more convenient to escape longer code blocks with a CDATA section, and
encode individual characters when they appear inline with text, as shown above. However, you could
use the following escaping and get the same result:
<p>
This is the <code>HelloWorld</code> class which prints
a <code><![CDATA[<hello>]]></code> element:
</p>
<div><pre>
public class HelloWorld {
public String print() {
return "<hello>world</hello>";
}
}
</pre></div>
Javadoc has a shortcut for escaping statements and wrapping them in a <code>
element: The {@code <hello>world<hello>} syntax. Use it whenever you need to
escape a statement in a regular Javadoc paragraph. This also works with code blocks in Javadoc
comments:
/**
* This is the <code>HelloWorld</code> class.
*
* <p>
* This is what it prints:
* </p>
*
* <div><pre>{@code
*
* <hello>world</hello>
*
* }</pre></div>
*
*/
public class HelloWorld {}
Anything inside the {@code ...} tag will be escaped with XML entities. You should not
use a CDATA block within Javadoc comments, you want to keep it backwards compatible
with HTML browsers. Regular Javadoc API documentation is not XHTML but HTML which does not
support CDATA. Although your Javadoc comment would work for Lemma documentation
generation, it would result in invalid Javadoc API documentation without Lemma.
Lemma will recognize any @link tags in your Javadoc comments and try to
match them by cross-referencing all your citations for the same Java package, method, or class.
Consider the following example:
/**
* This method calls
* the {@link example.helloworld.HelloWorld} class.
*/
public void callHelloWorld() {
new HelloWorld();
}
When you include this Javadoc comment with a Lemma citation, a regular XHTML anchor will
be created automatically. Lemma will try to match the target of the link to any of your citations.
So if you also have a citation of the HelloWorld class in your manual, the following link
will be automatically generated:
<div class="citation javadoc" id="javadoc.example.advanced.LinkingCitations.callHelloWorld..">
<div class="title">This method calls
the <a class="xref" href="#javadoc.example.helloworld.HelloWorld">Just print a hello</a> class.</div>
</div>
The title of the anchor will match the title of the target - if the target has a title. If neither the target or its title can be found, a warning message will be logged during processing and broken link placeholder will be set in the output XHTML.
When your Lemma documentation grows, you quickly realize that your master XHTML template file will grow large, too large to handle comfortably. You can use XInclude, an XML feature, to split your XHTML file into several smaller files.
Let's assume your master template looks as follows:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xi="http://www.w3.org/2001/XInclude">
<head>
<title>My Manual</title>
</head>
<body>
<div class="manual">
<xi:include href="chapter01.xhtml" xml:base="src/test/java/example/advanced/include/"/>
<xi:include href="chapter02/index.xhtml" xml:base="src/test/java/example/advanced/include/"/>
</div>
</body>
</html>
Note the additional namespace declaration on the root element. For any include instruction, you also have to specify the base directory. This is a relative location, depending on the current directory from which you execute the documentation build. (This should always be the same "current" directory when you use a build system such as Maven.)
This is how an included file looks like:
<div class="chapter" id="chapter.SecondChapter"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xi="http://www.w3.org/2001/XInclude">
<div class="title">The Second Chapter</div>
<div class="content">
<p>
This is the second chapter.
</p>
<xi:include href="somesection.xhtml"/>
</div>
</div>
Here, you can again declare the XInclude namespace and continue adding more fine-grained sections to your manual. You do not have to repeat the inclusion base anymore, only the "master" of your inclusion tree requires this. You have to explicitly declare a default namespace (the XHTML namespace) on the root element of each file, however.

