blob: 837333ddf0f7812991e11e74547077d38a48ab6d [file] [log] [blame]
/* gnu.classpath.tools.doclets.htmldoclet.HtmlDoclet
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
package gnu.classpath.tools.doclets.htmldoclet;
import gnu.classpath.tools.IOToolkit;
import gnu.classpath.tools.doclets.AbstractDoclet;
import gnu.classpath.tools.doclets.DocletConfigurationException;
import gnu.classpath.tools.doclets.DocletOption;
import gnu.classpath.tools.doclets.DocletOptionFile;
import gnu.classpath.tools.doclets.DocletOptionFlag;
import gnu.classpath.tools.doclets.DocletOptionString;
import gnu.classpath.tools.doclets.PackageGroup;
import gnu.classpath.tools.doclets.TagletPrinter;
import gnu.classpath.tools.doclets.InlineTagRenderer;
import gnu.classpath.tools.doclets.xmldoclet.HtmlRepairer;
import gnu.classpath.tools.taglets.GnuExtendedTaglet;
import gnu.classpath.tools.taglets.TagletContext;
import gnu.classpath.tools.java2xhtml.Java2xhtml;
import gnu.classpath.tools.StringToolkit;
import com.sun.javadoc.*;
import com.sun.tools.doclets.Taglet;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.SortedSet;
import java.util.TimeZone;
import java.util.TreeSet;
public class HtmlDoclet
extends AbstractDoclet
implements InlineTagRenderer
{
private static String filenameExtension = ".html";
/**
* Contains ExternalDocSet.
*/
private List externalDocSets = new LinkedList();
/**
* Contains String->ExternalDocSet.
*/
private Map packageNameToDocSet = new HashMap();
/**
* Cache for version string from resource /version.properties
*/
private String docletVersion;
/**
* For now, do not output a help page.
*/
private static final boolean outputHelpPage = false;
/**
* Stores the output encoding (either the one specified using
* -charset, or the platform default encoding).
*/
private String outputCharset;
private void printNavBar(HtmlPage output, String currentPage, ClassDoc currentClass)
{
output.beginDiv(CssClass.NAVBAR_TOP);
boolean overviewLevel
= ("overview".equals(currentPage)
|| "full-tree".equals(currentPage)
|| "index".equals(currentPage)
|| "split-index".equals(currentPage)
|| "serialized".equals(currentPage)
|| "deprecated".equals(currentPage)
|| "about".equals(currentPage)
);
if (!isSinglePackage()) {
if ("overview".equals(currentPage)) {
output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
output.print("Overview");
output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
}
else {
output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
output.beginAnchor(output.getPathToRoot() + "/overview-summary" + filenameExtension);
output.print("Overview");
output.endAnchor();
output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
}
output.print(" ");
}
if (!overviewLevel || isSinglePackage()) {
if ("package".equals(currentPage)) {
output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
output.print("Package");
output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
}
else {
output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
String packageHref;
if (isSinglePackage()) {
packageHref = output.getPathToRoot() + "/" + getPackageURL(getSinglePackage()) + "package-summary" + filenameExtension;
}
else {
packageHref = "package-summary" + filenameExtension;
}
output.beginAnchor(packageHref);
output.print("Package");
output.endAnchor();
output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
}
}
else {
output.beginSpan(CssClass.NAVBAR_ITEM_DISABLED);
output.print("Package");
output.endSpan(CssClass.NAVBAR_ITEM_DISABLED);
}
if (optionUse.getValue() || optionLinkSource.getValue()) {
output.print(" ");
if (null != currentClass) {
if ("class".equals(currentPage)) {
output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
output.print("Class");
output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
}
else {
output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
output.beginAnchor(currentClass.name() + filenameExtension);
output.print("Class");
output.endAnchor();
output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
}
}
else {
output.beginSpan(CssClass.NAVBAR_ITEM_DISABLED);
output.print("Class");
output.endSpan(CssClass.NAVBAR_ITEM_DISABLED);
}
if (optionUse.getValue()) {
output.print(" ");
if (null != currentClass) {
if ("uses".equals(currentPage)) {
output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
output.print("Use");
output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
}
else {
output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
output.beginAnchor(currentClass.name() + "-uses" + filenameExtension);
output.print("Use");
output.endAnchor();
output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
}
}
else {
output.beginSpan(CssClass.NAVBAR_ITEM_DISABLED);
output.print("Use");
output.endSpan(CssClass.NAVBAR_ITEM_DISABLED);
}
}
if (optionLinkSource.getValue()) {
output.print(" ");
if ("source".equals(currentPage)) {
output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
output.print("Source");
output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
}
else {
if (null != currentClass) {
output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
String targetClassName = currentClass.name();
String targetAnchor = "";
if (null != currentClass.containingClass()) {
targetClassName = getOuterClassDoc(currentClass).name();
targetAnchor = "#line." + currentClass.position().line();
}
output.beginAnchor(targetClassName + "-source" + filenameExtension + targetAnchor);
output.print("Source");
output.endAnchor();
output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
}
else {
output.beginSpan(CssClass.NAVBAR_ITEM_DISABLED);
output.print("Source");
output.endSpan(CssClass.NAVBAR_ITEM_DISABLED);
}
}
}
}
if (!optionNoTree.getValue()) {
output.print(" ");
if ("full-tree".equals(currentPage)
|| "package-tree".equals(currentPage)) {
output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
output.print("Tree");
output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
}
else {
output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
String treeHref;
if (isSinglePackage() && overviewLevel) {
treeHref = getPackageURL(getSinglePackage()) + "tree" + filenameExtension;
}
else {
treeHref = "tree" + filenameExtension;
}
output.beginAnchor(treeHref);
output.print("Tree");
output.endAnchor();
output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
}
}
output.print(" ");
String indexName;
if (optionSplitIndex.getValue()) {
indexName = "alphaindex-1";
}
else {
indexName = "alphaindex";
}
if ("index".equals(currentPage) || "split-index".equals(currentPage)) {
output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
output.print("Index");
output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
}
else {
output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
output.beginAnchor(output.getPathToRoot() + "/" + indexName + filenameExtension);
output.print("Index");
output.endAnchor();
output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
}
if (!optionNoDeprecatedList.getValue()) {
output.print(" ");
if ("deprecated".equals(currentPage)) {
output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
output.print("Deprecated");
output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
}
else {
output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
output.beginAnchor(output.getPathToRoot() + "/deprecated" + filenameExtension);
output.print("Deprecated");
output.endAnchor();
output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
}
}
if (outputHelpPage) {
if (!optionNoHelp.getValue()) {
output.print(" ");
if ("help".equals(currentPage)) {
output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
output.print("Help");
output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
}
else {
output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
output.beginAnchor(output.getPathToRoot() + "/help" + filenameExtension);
output.print("Help");
output.endAnchor();
output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
}
}
}
output.print(" ");
if ("about".equals(currentPage)) {
output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
output.print("About");
output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
}
else {
output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
output.beginAnchor(output.getPathToRoot() + "/about" + filenameExtension);
output.print("About");
output.endAnchor();
output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
}
output.endDiv(CssClass.NAVBAR_TOP);
}
private void printNavBarTopRow(HtmlPage output, String currentPage, ClassDoc currentClass)
{
output.beginRow();
output.beginCell(CssClass.NAVBAR_TOP);
printNavBar(output, currentPage, currentClass);
output.endCell();
if (null != optionHeader.getValue()) {
output.beginCell(CssClass.NAVBAR_TOP_HEADER);
output.print(replaceDocRoot(output, optionHeader.getValue()));
output.endCell();
}
output.endRow();
}
private void printNavBarTopNaviCell(HtmlPage output)
{
output.beginCell(CssClass.NAVBAR_TOP_NAVI);
output.beginAnchor(output.getPathToRoot() + "/index" + filenameExtension, "Show in a frameset", "_top");
output.print("Frames");
output.endAnchor();
output.print(" | ");
output.beginAnchor(output.getFile().getName(), "Show without frames", "_top");
output.print("No Frames");
output.endAnchor();
output.print(" ");
output.endCell();
}
private void printNavBarTop(HtmlPage output, String currentPage)
{
printNavBarTop(output, currentPage, null, null, null);
}
private void printNavBarTop(HtmlPage output, String currentPage,
ClassDoc currentClass, Object prev, Object next)
{
if (!optionNoNavBar.getValue()) {
output.beginTable(CssClass.NAVBAR_TOP);
printNavBarTopRow(output, currentPage, currentClass);
output.beginRow();
if ("class".equals(currentPage)) {
output.beginCell(CssClass.NAVBAR_TOP_NAVI);
ClassDoc prevClass = (ClassDoc)prev;
ClassDoc nextClass = (ClassDoc)next;
if (null != prevClass) {
output.anchor(getClassDocURL(output, prevClass), "Prev Class");
}
else {
output.print("Prev Class");
}
output.print(" | ");
if (null != nextClass) {
output.anchor(getClassDocURL(output, nextClass), "Next Class");
}
else {
output.print("Next Class");
}
output.endCell();
}
else if ("split-index".equals(currentPage)) {
output.beginCell(CssClass.NAVBAR_TOP_NAVI);
Integer prevLetter = (Integer)prev;
Integer nextLetter = (Integer)next;
if (null != prevLetter) {
output.anchor("alphaindex-" + prevLetter + filenameExtension, "Prev Letter");
}
else {
output.print("Prev Letter");
}
output.print(" | ");
if (null != nextLetter) {
output.anchor("alphaindex-" + nextLetter + filenameExtension, "Next Letter");
}
else {
output.print("Next Letter");
}
output.endCell();
}
else {
output.beginCell(CssClass.NAVBAR_TOP_NAVI);
output.endCell();
}
printNavBarTopNaviCell(output);
output.endRow();
if ("class".equals(currentPage)) {
output.beginRow();
output.beginCell(CssClass.NAVBAR_TOP_NAVI);
output.print("Summary: ");
if (currentClass.innerClasses().length > 0) {
output.anchor("#summary-inner", "Nested");
}
else {
output.print("Nested");
}
output.print(" | ");
if (currentClass.fields().length > 0) {
output.anchor("#summary-fields", "Field");
}
else {
output.print("Field");
}
output.print(" | ");
if (currentClass.methods().length > 0) {
output.anchor("#summary-methods", "Method");
}
else {
output.print("Method");
}
output.print(" | ");
if (currentClass.constructors().length > 0) {
output.anchor("#summary-constructors", "Constr");
}
else {
output.print("Constr");
}
output.endCell();
output.beginCell(CssClass.NAVBAR_TOP_NAVI);
output.print("Detail: ");
if (currentClass.innerClasses().length > 0) {
output.anchor("#detail-inner", "Nested");
}
else {
output.print("Nested");
}
output.print(" | ");
if (currentClass.fields().length > 0) {
output.anchor("#detail-fields", "Field");
}
else {
output.print("Field");
}
output.print(" | ");
if (currentClass.methods().length > 0) {
output.anchor("#detail-methods", "Method");
}
else {
output.print("Method");
}
output.print(" | ");
if (currentClass.constructors().length > 0) {
output.anchor("#detail-constructors", "Constr");
}
else {
output.print("Constr");
}
output.endCell();
output.endRow();
}
output.endTable();
}
}
private void printNavBarTopPackage(HtmlPage output, String currentPage,
PackageDoc prevPackage, PackageDoc nextPackage)
{
if (!optionNoNavBar.getValue()) {
output.beginTable(CssClass.NAVBAR_TOP);
printNavBarTopRow(output, currentPage, null);
output.beginRow();
output.beginCell(CssClass.NAVBAR_TOP_NAVI);
if (null != prevPackage) {
output.anchor(output.getPathToRoot() + "/" + getPackageURL(prevPackage) + "package-summary" + filenameExtension, "Prev Package");
}
else {
output.print("Prev Package");
}
output.print(" | ");
if (null != nextPackage) {
output.anchor(output.getPathToRoot() + "/" + getPackageURL(nextPackage) + "package-summary" + filenameExtension, "Next Package");
}
else {
output.print("Next Package");
}
output.endCell();
printNavBarTopNaviCell(output);
output.endRow();
output.endTable();
}
}
private void printNavBarBottom(HtmlPage output, String currentPage)
{
printNavBarBottom(output, currentPage, null);
}
private void printNavBarBottom(HtmlPage output, String currentPage, ClassDoc currentClass)
{
if ("class".equals(currentPage)) {
String boilerplate = null;
Tag[] boilerplateTags = getOuterClassDoc(currentClass).tags("@boilerplate");
if (boilerplateTags.length > 0) {
boilerplate = boilerplateTags[0].text();
}
if (null != boilerplate) {
output.hr();
output.beginDiv(CssClass.CLASS_BOILERPLATE);
output.print(boilerplate);
output.endDiv(CssClass.CLASS_BOILERPLATE);
output.hr();
}
}
if (!optionNoNavBar.getValue()) {
output.beginDiv(CssClass.NAVBAR_BOTTOM_SPACER);
output.print(" ");
output.endDiv(CssClass.NAVBAR_BOTTOM_SPACER);
output.beginTable(CssClass.NAVBAR_BOTTOM);
output.beginRow();
output.beginCell();
printNavBar(output, currentPage, currentClass);
output.endCell();
if (null != optionFooter.getValue()) {
output.beginCell();
output.print(replaceDocRoot(output, optionFooter.getValue()));
output.endCell();
}
output.endRow();
output.endTable();
}
if (null != optionBottom.getValue()) {
output.hr();
output.print(replaceDocRoot(output, optionBottom.getValue()));
}
}
private void printPackagePageClasses(HtmlPage output, ClassDoc[] classDocs, String header)
{
if (classDocs.length > 0) {
output.beginDiv(CssClass.TABLE_CONTAINER);
output.beginTable(CssClass.PACKAGE_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
output.rowDiv(CssClass.TABLE_HEADER, header);
for (int i=0; i<classDocs.length; ++i) {
ClassDoc classDoc = classDocs[i];
if (classDoc.isIncluded()) {
output.beginRow();
output.beginCell(CssClass.PACKAGE_SUMMARY_LEFT);
printType(output, classDoc);
output.endCell();
output.beginCell(CssClass.PACKAGE_SUMMARY_RIGHT);
printTags(output, classDoc, classDoc.firstSentenceTags(), true);
output.endCell();
output.endRow();
}
}
output.endTable();
output.endDiv(CssClass.TABLE_CONTAINER);
output.print("\n");
}
}
private void printPackagesListFile()
throws IOException
{
PrintWriter out
= new PrintWriter(new OutputStreamWriter(new FileOutputStream(new File(getTargetDirectory(),
"package-list")),
"UTF-8"));
PackageDoc[] packages = getRootDoc().specifiedPackages();
for (int i=0; i<packages.length; ++i) {
String packageName = packages[i].name();
if (packageName.length() > 0) {
out.println(packageName);
}
}
out.close();
}
private void printPackagePage(File packageDir, String pathToRoot,
PackageDoc packageDoc,
PackageDoc prevPackageDoc,
PackageDoc nextPackageDoc)
throws IOException
{
HtmlPage output = newHtmlPage(new File(packageDir, "package-summary" + filenameExtension),
pathToRoot);
Set keywords = new LinkedHashSet();
keywords.add(packageDoc.name() + " packages");
output.beginPage(getPageTitle(packageDoc.name()), getOutputCharset(),
keywords, getStylesheets());
output.beginBody(CssClass.BODY_CONTENT_PACKAGE);
printNavBarTopPackage(output, "package", prevPackageDoc, nextPackageDoc);
output.beginDiv(CssClass.PACKAGE_TITLE);
output.print("Package ");
if (packageDoc.name().length() > 0) {
output.print(packageDoc.name());
}
else {
output.print("&lt;Unnamed&gt;");
}
output.endDiv(CssClass.PACKAGE_TITLE);
output.beginDiv(CssClass.PACKAGE_DESCRIPTION_TOP);
printTags(output, packageDoc, packageDoc.firstSentenceTags(), true);
output.endDiv(CssClass.PACKAGE_DESCRIPTION_TOP);
printPackagePageClasses(output, packageDoc.interfaces(),
"Interface Summary");
printPackagePageClasses(output, packageDoc.ordinaryClasses(),
"Class Summary");
printPackagePageClasses(output, packageDoc.exceptions(),
"Exception Summary");
printPackagePageClasses(output, packageDoc.errors(),
"Error Summary");
output.anchorName("description");
output.beginDiv(CssClass.PACKAGE_DESCRIPTION_FULL);
printTags(output, packageDoc, packageDoc.inlineTags(), false);
output.endDiv(CssClass.PACKAGE_DESCRIPTION_FULL);
printNavBarBottom(output, "package");
output.endBody();
output.endPage();
output.close();
}
static class TreeNode
implements Comparable
{
ClassDoc classDoc;
SortedSet children = new TreeSet();
TreeNode(ClassDoc classDoc) {
TreeNode.this.classDoc = classDoc;
}
public boolean equals(Object other)
{
return classDoc.equals(((TreeNode)other).classDoc);
}
public int compareTo(Object other)
{
return classDoc.compareTo(((TreeNode)other).classDoc);
}
public int hashCode()
{
return classDoc.hashCode();
}
}
private TreeNode addClassTreeNode(Map treeMap, ClassDoc classDoc)
{
TreeNode node = (TreeNode)treeMap.get(classDoc.qualifiedName());
if (null == node) {
node = new TreeNode(classDoc);
treeMap.put(classDoc.qualifiedName(), node);
ClassDoc superClassDoc = (ClassDoc)classDoc.superclass();
if (null != superClassDoc) {
TreeNode parentNode = addClassTreeNode(treeMap, superClassDoc);
parentNode.children.add(node);
}
}
return node;
}
private TreeNode addInterfaceTreeNode(Map treeMap, ClassDoc classDoc)
{
TreeNode node = (TreeNode)treeMap.get(classDoc.qualifiedName());
if (null == node) {
node = new TreeNode(classDoc);
treeMap.put(classDoc.qualifiedName(), node);
ClassDoc[] superInterfaces = classDoc.interfaces();
if (null != superInterfaces && superInterfaces.length > 0) {
for (int i=0; i<superInterfaces.length; ++i) {
TreeNode parentNode = addInterfaceTreeNode(treeMap, superInterfaces[i]);
parentNode.children.add(node);
}
}
else {
TreeNode rootNode = (TreeNode)treeMap.get("<root>");
if (null == rootNode) {
rootNode = new TreeNode(null);
treeMap.put("<root>", rootNode);
}
rootNode.children.add(node);
}
}
return node;
}
private void printPackageTreeRec(HtmlPage output, TreeNode node, TreeNode parentNode)
{
output.beginElement("li", "class", "node");
output.beginElement("div");
if (node.classDoc.isIncluded()) {
String packageName = node.classDoc.containingPackage().name();
if (packageName.length() > 0) {
output.print(packageName);
output.print(".");
}
output.beginSpan(CssClass.TREE_LINK);
printType(output, node.classDoc);
output.endSpan(CssClass.TREE_LINK);
}
else {
output.print(possiblyQualifiedName(node.classDoc));
}
ClassDoc[] interfaces = node.classDoc.interfaces();
ClassDoc parentClassDoc = null;
if (null != parentNode) {
parentClassDoc = parentNode.classDoc;
}
if (interfaces.length > 0
&& !(interfaces.length == 1 && interfaces[0].equals(parentClassDoc))) {
if (node.classDoc.isInterface()) {
output.print(" (also implements ");
}
else {
output.print(" (implements ");
}
boolean firstItem = true;
for (int i=0; i<interfaces.length; ++i) {
ClassDoc implemented = interfaces[i];
if (!implemented.equals(parentClassDoc)) {
if (!firstItem) {
output.print(", ");
}
firstItem = false;
if (implemented.isIncluded()) {
output.print(implemented.containingPackage().name());
output.print(".");
printType(output, implemented);
}
else {
output.print(possiblyQualifiedName(implemented));
}
}
}
output.print(")");
}
output.endElement("div");
output.endElement("li");
if (!node.children.isEmpty()) {
output.beginElement("li", "class", "level");
output.beginElement("ul");
Iterator it = node.children.iterator();
while (it.hasNext()) {
TreeNode child = (TreeNode)it.next();
printPackageTreeRec(output, child, node);
}
output.endElement("ul");
output.endElement("li");
}
}
private void printClassTree(HtmlPage output, ClassDoc[] classDocs)
{
Map classTreeMap = new HashMap();
for (int i=0; i<classDocs.length; ++i) {
ClassDoc classDoc = classDocs[i];
if (!classDoc.isInterface()) {
addClassTreeNode(classTreeMap, classDoc);
}
}
TreeNode root = (TreeNode)classTreeMap.get("java.lang.Object");
if (null != root) {
output.div(CssClass.PACKAGE_TREE_SECTION_TITLE, "Class Hierarchy");
output.beginDiv(CssClass.PACKAGE_TREE);
printPackageTreeRec(output, root, null);
output.endDiv(CssClass.PACKAGE_TREE);
}
}
private void printInterfaceTree(HtmlPage output, ClassDoc[] classDocs)
{
Map interfaceTreeMap = new HashMap();
for (int i=0; i<classDocs.length; ++i) {
ClassDoc classDoc = classDocs[i];
if (classDoc.isInterface()) {
addInterfaceTreeNode(interfaceTreeMap, classDoc);
}
}
TreeNode interfaceRoot = (TreeNode)interfaceTreeMap.get("<root>");
if (null != interfaceRoot) {
Iterator it = interfaceRoot.children.iterator();
if (it.hasNext()) {
output.div(CssClass.PACKAGE_TREE_SECTION_TITLE, "Interface Hierarchy");
output.beginDiv(CssClass.PACKAGE_TREE);
while (it.hasNext()) {
TreeNode node = (TreeNode)it.next();
printPackageTreeRec(output, node, null);
}
output.endDiv(CssClass.PACKAGE_TREE);
}
}
}
private void printPackageTreePage(File packageDir, String pathToRoot, PackageDoc packageDoc)
throws IOException
{
HtmlPage output = newHtmlPage(new File(packageDir,
"tree" + filenameExtension),
pathToRoot);
output.beginPage(getPageTitle(packageDoc.name() + " Hierarchy"),
getOutputCharset(),
getStylesheets());
output.beginBody(CssClass.BODY_CONTENT_PACKAGE_TREE);
printNavBarTop(output, "package-tree");
output.div(CssClass.PACKAGE_TREE_TITLE, "Hierarchy for Package " + packageDoc.name());
ClassDoc[] classDocs = packageDoc.allClasses();
printClassTree(output, classDocs);
printInterfaceTree(output, classDocs);
printNavBarBottom(output, "package-tree");
output.endBody();
output.endPage();
output.close();
}
private void printFullTreePage()
throws IOException
{
HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
"tree" + filenameExtension),
".");
output.beginPage(getPageTitle("Hierarchy"),
getOutputCharset(),
getStylesheets());
output.beginBody(CssClass.BODY_CONTENT_FULL_TREE);
printNavBarTop(output, "full-tree");
output.div(CssClass.PACKAGE_TREE_TITLE, "Hierarchy for All Packages");
output.beginDiv(CssClass.FULL_TREE_PACKAGELIST);
output.div(CssClass.FULL_TREE_PACKAGELIST_HEADER, "Package Hierarchies:");
output.beginDiv(CssClass.FULL_TREE_PACKAGELIST_ITEM);
Set allPackages = getAllPackages();
Iterator it = allPackages.iterator();
while (it.hasNext()) {
PackageDoc packageDoc = (PackageDoc)it.next();
output.beginAnchor(getPackageURL(packageDoc) + "tree" + filenameExtension);
output.print(packageDoc.name());
output.endAnchor();
if (it.hasNext()) {
output.print(", ");
}
}
output.endDiv(CssClass.FULL_TREE_PACKAGELIST_ITEM);
output.endDiv(CssClass.FULL_TREE_PACKAGELIST);
ClassDoc[] classDocs = getRootDoc().classes();
printClassTree(output, classDocs);
printInterfaceTree(output, classDocs);
printNavBarBottom(output, "full-tree");
output.endBody();
output.endPage();
output.close();
}
private void printIndexEntry(HtmlPage output, Doc entry)
{
output.beginDiv(CssClass.INDEX_ENTRY);
output.beginDiv(CssClass.INDEX_ENTRY_KEY);
String anchor = null;
String description = null;
if (entry instanceof PackageDoc) {
output.beginAnchor(getPackageURL((PackageDoc)entry) + "package-summary" + filenameExtension);
output.print(entry.name());
output.endAnchor();
output.print(" - package");
}
else if (entry instanceof ClassDoc) {
ClassDoc classDoc = (ClassDoc)entry;
output.beginAnchor(getClassURL(classDoc));
output.print(entry.name() + getTypeParameters(classDoc));
output.endAnchor();
output.print(" - ");
if (entry.isInterface()) {
output.print("interface ");
}
else if (entry.isException()) {
output.print("exception ");
}
else if (entry.isError()) {
output.print("error ");
}
else {
output.print("class ");
}
String packageName = classDoc.containingPackage().name();
if (packageName.length() > 0) {
output.print(packageName);
output.print(".");
}
printType(output, classDoc);
}
else {
ProgramElementDoc memberDoc = (ProgramElementDoc)entry;
output.beginAnchor(getMemberDocURL(output, memberDoc));
output.print(entry.name());
if (memberDoc instanceof ExecutableMemberDoc) {
output.print(((ExecutableMemberDoc)memberDoc).signature());
}
output.endAnchor();
output.print(" - ");
if (memberDoc.isStatic()) {
output.print("static ");
}
if (entry.isConstructor()) {
output.print("constructor for class ");
}
else if (entry.isMethod()) {
output.print("method in class ");
}
else if (entry.isField()) {
output.print("field in class ");
}
ClassDoc containingClass = memberDoc.containingClass();
String packageName = containingClass.containingPackage().name();
if (packageName.length() > 0) {
output.print(packageName);
output.print(".");
}
printType(output, containingClass);
}
output.endDiv(CssClass.INDEX_ENTRY_KEY);
output.beginDiv(CssClass.INDEX_ENTRY_DESCRIPTION);
printTags(output, entry, entry.firstSentenceTags(), true);
output.endDiv(CssClass.INDEX_ENTRY_DESCRIPTION);
output.endDiv(CssClass.INDEX_ENTRY);
}
private void printFrameSetPage()
throws IOException
{
HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
"index" + filenameExtension),
".",
HtmlPage.DOCTYPE_FRAMESET);
String title = getWindowTitle();
output.beginPage(title, getOutputCharset(), getStylesheets());
output.beginElement("frameset", "cols", "20%,80%");
String contentURL;
if (isSinglePackage()) {
output.atomicElement("frame",
new String[] { "src", "name" },
new String[] { getPackageURL(getSinglePackage()) + "classes" + filenameExtension, "classes" });
contentURL = getPackageURL(getSinglePackage()) + "package-summary.html";
}
else {
output.beginElement("frameset", "rows", "25%,75%");
output.atomicElement("frame",
new String[] { "src", "name" },
new String[] { "all-packages" + filenameExtension, "packages" });
output.atomicElement("frame",
new String[] { "src", "name" },
new String[] { "all-classes" + filenameExtension, "classes" });
output.endElement("frameset");
contentURL = "overview-summary" + filenameExtension;
}
output.atomicElement("frame",
new String[] { "src", "name" },
new String[] { contentURL, "content" });
output.endElement("frameset");
output.endPage();
output.close();
}
private void printPackagesMenuPage()
throws IOException
{
HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
"all-packages" + filenameExtension),
".");
output.beginPage(getPageTitle("Package Menu"), getOutputCharset(), getStylesheets());
output.beginBody(CssClass.BODY_MENU_PACKAGES, false);
output.beginSpan(CssClass.PACKAGE_MENU_ENTRY);
output.beginAnchor("all-classes" + filenameExtension,
null,
"classes");
output.print("All Classes");
output.endAnchor();
output.endSpan(CssClass.PACKAGE_MENU_ENTRY);
output.div(CssClass.PACKAGE_MENU_TITLE, "Packages");
output.beginDiv(CssClass.PACKAGE_MENU_LIST);
Set packageDocs = getAllPackages();
Iterator it = packageDocs.iterator();
while (it.hasNext()) {
PackageDoc packageDoc = (PackageDoc)it.next();
output.beginSpan(CssClass.PACKAGE_MENU_ENTRY);
output.beginAnchor(getPackageURL(packageDoc) + "classes" + filenameExtension,
null,
"classes");
if (packageDoc.name().length() > 0) {
output.print(packageDoc.name());
}
else {
output.print("&lt;unnamed package&gt;");
}
output.endAnchor();
output.endSpan(CssClass.PACKAGE_MENU_ENTRY);
output.br();
}
output.endDiv(CssClass.PACKAGE_MENU_LIST);
output.endBody();
output.endPage();
output.close();
}
private void printClassMenuEntry(HtmlPage output, ClassDoc classDoc)
{
CssClass entryClass;
if (classDoc.isInterface()) {
entryClass = CssClass.CLASS_MENU_ENTRY_INTERFACE;
}
else {
entryClass = CssClass.CLASS_MENU_ENTRY_CLASS;
}
output.beginSpan(entryClass);
output.beginAnchor(getClassDocURL(output, classDoc),
classDoc.qualifiedTypeName(),
"content");
output.print(classDoc.name());
output.endAnchor();
output.endSpan(entryClass);
output.br();
}
private void printClassMenuSection(HtmlPage output, Collection classDocs, String header)
{
if (!classDocs.isEmpty()) {
output.div(CssClass.CLASS_MENU_SUBTITLE, header);
Iterator it = classDocs.iterator();
while (it.hasNext()) {
ClassDoc classDoc = (ClassDoc)it.next();
printClassMenuEntry(output, classDoc);
}
}
}
private void printClassMenuList(HtmlPage output, ClassDoc[] classDocs, boolean categorized)
{
output.beginDiv(CssClass.CLASS_MENU_LIST);
if (categorized) {
Set classes = new TreeSet();
Set interfaces = new TreeSet();
Set exceptions = new TreeSet();
Set errors = new TreeSet();
for (int i=0; i<classDocs.length; ++i) {
ClassDoc classDoc = classDocs[i];
if (classDoc.isInterface()) {
interfaces.add(classDoc);
}
else if (classDoc.isException()) {
exceptions.add(classDoc);
}
else if (classDoc.isError()) {
errors.add(classDoc);
}
else {
classes.add(classDoc);
}
}
printClassMenuSection(output, interfaces, "Interfaces");
printClassMenuSection(output, classes, "Classes");
printClassMenuSection(output, exceptions, "Exceptions");
printClassMenuSection(output, errors, "Errors");
}
else {
for (int i=0; i<classDocs.length; ++i) {
ClassDoc classDoc = classDocs[i];
if (classDoc.isIncluded()) {
printClassMenuEntry(output, classDoc);
}
}
}
output.endDiv(CssClass.CLASS_MENU_LIST);
}
private void printAllClassesMenuPage()
throws IOException
{
HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
"all-classes" + filenameExtension),
".");
output.beginPage(getPageTitle("Class Menu"), getOutputCharset(), getStylesheets());
output.beginBody(CssClass.BODY_MENU_CLASSES, false);
output.div(CssClass.CLASS_MENU_TITLE, "All Classes");
printClassMenuList(output, getRootDoc().classes(), false);
output.endBody();
output.endPage();
output.close();
}
private void printPackageClassesMenuPage(File packageDir, String pathToRoot, PackageDoc packageDoc)
throws IOException
{
HtmlPage output = newHtmlPage(new File(packageDir,
"classes" + filenameExtension),
pathToRoot);
output.beginPage(getPageTitle(packageDoc.name() + " Class Menu"),
getOutputCharset(), getStylesheets());
output.beginBody(CssClass.BODY_MENU_CLASSES, false);
output.beginDiv(CssClass.CLASS_MENU_TITLE);
output.beginAnchor("package-summary" + filenameExtension, "", "content");
if (packageDoc.name().length() > 0) {
output.print(packageDoc.name());
}
else {
output.print("&lt;Unnamed&gt;");
}
output.endAnchor();
output.endDiv(CssClass.CLASS_MENU_TITLE);
printClassMenuList(output, packageDoc.allClasses(), true);
output.endBody();
output.endPage();
output.close();
}
private void printSplitIndex()
throws IOException
{
Map categorizedIndex = getCategorizedIndex();
Iterator it = categorizedIndex.keySet().iterator();
int n = 1;
int count = categorizedIndex.size();
while (it.hasNext()) {
Character c = (Character)it.next();
List classList = (List)categorizedIndex.get(c);
printIndexPage(n++, count, c, classList);
}
}
private void printIndexPage()
throws IOException
{
printIndexPage(0, 0, null, null);
}
private void printIndexPage(int index, int maxIndex, Character letter, List classList)
throws IOException
{
String pageName = "alphaindex";
if (null != letter) {
pageName += "-" + index;
}
HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
pageName + filenameExtension),
".");
output.beginPage(getPageTitle("Alphabetical Index"),
getOutputCharset(),
getStylesheets());
output.beginBody(CssClass.BODY_CONTENT_INDEX);
if (null == letter) {
printNavBarTop(output, "index");
}
else {
printNavBarTop(output, "split-index", null,
(index > 1) ? new Integer(index - 1) : null,
(index < maxIndex) ? new Integer(index + 1) : null);
}
{
String title;
if (null == letter) {
title = "Alphabetical Index";
}
else {
title = "Alphabetical Index: " + letter;
}
output.div(CssClass.INDEX_TITLE, title);
if (null != letter || getCategorizedIndex().keySet().size() > 1) {
output.beginDiv(CssClass.INDEX_LETTERS);
Iterator it = getCategorizedIndex().keySet().iterator();
int n = 1;
while (it.hasNext()) {
Character c = (Character)it.next();
output.beginSpan(CssClass.INDEX_LETTER);
if (letter != null) {
output.beginAnchor("alphaindex-" + n + filenameExtension);
}
else {
output.beginAnchor("#" + c);
}
output.print(c.toString());
output.endAnchor();
output.endSpan(CssClass.INDEX_LETTER);
output.beginSpan(CssClass.INDEX_LETTER_SPACER);
output.print(" ");
output.endSpan(CssClass.INDEX_LETTER_SPACER);
++n;
}
}
output.endDiv(CssClass.INDEX_LETTERS);
}
if (null != letter) {
printIndexCategory(output, letter, classList);
}
else {
Map categorizedIndex = getCategorizedIndex();
Iterator categoryIt = categorizedIndex.keySet().iterator();
while (categoryIt.hasNext()) {
letter = (Character)categoryIt.next();
classList = (List)categorizedIndex.get(letter);
output.anchorName(letter.toString());
printIndexCategory(output, letter, classList);
}
}
printNavBarBottom(output, "index");
output.endBody();
output.endPage();
output.close();
}
private void printIndexCategory(HtmlPage output, Character letter, List classList)
{
Iterator it = classList.iterator();
output.div(CssClass.INDEX_CATEGORY_HEADER, letter.toString());
output.beginDiv(CssClass.INDEX_CATEGORY);
while (it.hasNext()) {
Doc entry = (Doc)it.next();
printIndexEntry(output, entry);
}
output.endDiv(CssClass.INDEX_CATEGORY);
}
private void printDeprecationSummary(HtmlPage output, List docs, String header)
{
if (!docs.isEmpty()) {
output.beginDiv(CssClass.TABLE_CONTAINER);
output.beginTable(CssClass.DEPRECATION_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
output.rowDiv(CssClass.TABLE_HEADER, header);
Iterator it = docs.iterator();
while (it.hasNext()) {
Doc doc = (Doc)it.next();
output.beginRow();
output.beginCell(CssClass.DEPRECATION_SUMMARY_LEFT);
if (doc instanceof Type) {
printType(output, (Type)doc);
}
else {
ProgramElementDoc memberDoc = (ProgramElementDoc)doc;
output.beginAnchor(getMemberDocURL(output, memberDoc));
output.print(memberDoc.containingClass().qualifiedName());
output.print(".");
output.print(memberDoc.name());
if (memberDoc instanceof ExecutableMemberDoc) {
output.print(((ExecutableMemberDoc)memberDoc).flatSignature());
}
output.endAnchor();
}
output.beginDiv(CssClass.DEPRECATION_SUMMARY_DESCRIPTION);
printTags(output, doc, doc.tags("deprecated")[0].firstSentenceTags(), true);
output.endDiv(CssClass.DEPRECATION_SUMMARY_DESCRIPTION);
output.endCell();
output.endRow();
}
output.endTable();
output.endDiv(CssClass.TABLE_CONTAINER);
output.print("\n");
}
}
private void printSerializationPage()
throws IOException
{
HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
"serialized-form" + filenameExtension),
".");
output.beginPage(getPageTitle("Serialized Form"),
getOutputCharset(),
getStylesheets());
output.beginBody(CssClass.BODY_CONTENT_DEPRECATED);
printNavBarTop(output, "serialized");
output.div(CssClass.SERIALIZED_TITLE, "Serialized Form");
Iterator it = getAllPackages().iterator();
while (it.hasNext()) {
PackageDoc packageDoc = (PackageDoc)it.next();
List serializableClasses = new LinkedList();
ClassDoc[] classes = packageDoc.allClasses();
for (int i=0; i<classes.length; ++i) {
ClassDoc classDoc = classes[i];
if (classDoc.isSerializable() || classDoc.isExternalizable()) {
serializableClasses.add(classDoc);
}
}
if (!serializableClasses.isEmpty()) {
output.div(CssClass.SERIALIZED_PACKAGE_HEADER, "Package " + packageDoc.name());
Iterator cit = serializableClasses.iterator();
while (cit.hasNext()) {
ClassDoc classDoc = (ClassDoc)cit.next();
output.anchorName(classDoc.qualifiedTypeName());
output.beginDiv(CssClass.SERIALIZED_CLASS_HEADER);
output.print("Class ");
printType(output, classDoc, true);
output.print(" extends ");
printType(output, classDoc.superclass());
output.print(" implements Serializable");
output.endDiv(CssClass.SERIALIZED_CLASS_HEADER);
FieldDoc serialVersionUidField = findField(classDoc, "serialVersionUID");
if (null != serialVersionUidField
&& serialVersionUidField.isFinal()
&& serialVersionUidField.isStatic()
&& serialVersionUidField.type().typeName().equals("long")) {
String fieldValue = serialVersionUidField.constantValueExpression();
if (null != fieldValue) {
output.beginDiv(CssClass.SERIALIZED_SVUID_OUTER);
output.span(CssClass.SERIALIZED_SVUID_HEADER, "serialVersionUID: ");
output.span(CssClass.SERIALIZED_SVUID_VALUE, fieldValue);
output.endDiv(CssClass.SERIALIZED_SVUID_OUTER);
}
}
printMemberDetails(output,
classDoc.serializationMethods(),
"Serialization Methods",
true, null);
printMemberDetails(output,
classDoc.serializableFields(),
"Serialized Fields",
true, null);
}
}
}
printNavBarBottom(output, "serialized");
output.endBody();
output.endPage();
output.close();
}
private void printDeprecationPage()
throws IOException
{
HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
"deprecated" + filenameExtension),
".");
output.beginPage(getPageTitle("Deprecated API"),
getOutputCharset(),
getStylesheets());
output.beginBody(CssClass.BODY_CONTENT_DEPRECATED);
printNavBarTop(output, "deprecated");
output.div(CssClass.DEPRECATION_TITLE, "Deprecated API");
List deprecatedInterfaces = new LinkedList();
List deprecatedExceptions = new LinkedList();
List deprecatedErrors = new LinkedList();
List deprecatedClasses = new LinkedList();
List deprecatedFields = new LinkedList();
List deprecatedMethods = new LinkedList();
List deprecatedConstructors = new LinkedList();
ClassDoc[] classDocs = getRootDoc().classes();
for (int i=0; i<classDocs.length; ++i) {
ClassDoc classDoc = classDocs[i];
{
Tag[] deprecatedTags = classDoc.tags("deprecated");
if (null != deprecatedTags && deprecatedTags.length > 0) {
if (classDoc.isInterface()) {
deprecatedInterfaces.add(classDoc);
}
else if (classDoc.isException()) {
deprecatedExceptions.add(classDoc);
}
else if (classDoc.isError()) {
deprecatedErrors.add(classDoc);
}
else {
deprecatedClasses.add(classDoc);
}
}
}
ConstructorDoc[] constructors = classDoc.constructors();
for (int j=0; j<constructors.length; ++j) {
Tag[] deprecatedTags = constructors[j].tags("deprecated");
if (null != deprecatedTags && deprecatedTags.length > 0) {
deprecatedConstructors.add(constructors[j]);
}
}
MethodDoc[] methods = classDoc.methods();
for (int j=0; j<methods.length; ++j) {
Tag[] deprecatedTags = methods[j].tags("deprecated");
if (null != deprecatedTags && deprecatedTags.length > 0) {
deprecatedMethods.add(methods[j]);
}
}
FieldDoc[] fields = classDoc.fields();
for (int j=0; j<fields.length; ++j) {
Tag[] deprecatedTags = fields[j].tags("deprecated");
if (null != deprecatedTags && deprecatedTags.length > 0) {
deprecatedFields.add(fields[j]);
}
}
}
if (!deprecatedInterfaces.isEmpty()
|| !deprecatedClasses.isEmpty()
|| !deprecatedExceptions.isEmpty()
|| !deprecatedErrors.isEmpty()
|| !deprecatedFields.isEmpty()
|| !deprecatedMethods.isEmpty()
|| !deprecatedConstructors.isEmpty()) {
output.beginDiv(CssClass.DEPRECATION_TOC);
output.div(CssClass.DEPRECATION_TOC_HEADER, "Contents");
output.beginDiv(CssClass.DEPRECATION_TOC_LIST);
if (!deprecatedInterfaces.isEmpty()) {
output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
output.anchor("#interfaces", "Deprecated Interfaces");
output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
}
if (!deprecatedClasses.isEmpty()) {
output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
output.anchor("#classes", "Deprecated Classes");
output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
}
if (!deprecatedExceptions.isEmpty()) {
output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
output.anchor("#exceptions", "Deprecated Exceptions");
output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
}
if (!deprecatedErrors.isEmpty()) {
output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
output.anchor("#errors", "Deprecated Errors");
output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
}
if (!deprecatedFields.isEmpty()) {
output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
output.anchor("#fields", "Deprecated Fields");
output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
}
if (!deprecatedMethods.isEmpty()) {
output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
output.anchor("#methods", "Deprecated Methods");
output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
}
if (!deprecatedConstructors.isEmpty()) {
output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
output.anchor("#constructors", "Deprecated Constructors");
output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
}
output.endDiv(CssClass.DEPRECATION_TOC_LIST);
output.endDiv(CssClass.DEPRECATION_TOC);
output.beginDiv(CssClass.DEPRECATION_LIST);
output.anchorName("interfaces");
printDeprecationSummary(output, deprecatedInterfaces, "Deprecated Interfaces");
output.anchorName("classes");
printDeprecationSummary(output, deprecatedClasses, "Deprecated Classes");
output.anchorName("exceptions");
printDeprecationSummary(output, deprecatedExceptions, "Deprecated Exceptions");
output.anchorName("errors");
printDeprecationSummary(output, deprecatedErrors, "Deprecated Errors");
output.anchorName("fields");
printDeprecationSummary(output, deprecatedFields, "Deprecated Fields");
output.anchorName("methods");
printDeprecationSummary(output, deprecatedMethods, "Deprecated Methods");
output.anchorName("constructors");
printDeprecationSummary(output, deprecatedConstructors, "Deprecated Constructors");
output.endDiv(CssClass.DEPRECATION_LIST);
}
else {
output.beginDiv(CssClass.DEPRECATION_EMPTY);
output.print("No deprecated classes or class members in this API.");
output.endDiv(CssClass.DEPRECATION_EMPTY);
}
printNavBarBottom(output, "deprecated");
output.endBody();
output.endPage();
output.close();
}
private void printAboutPage()
throws IOException
{
HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
"about" + filenameExtension),
".");
output.beginPage(getPageTitle("About"),
getOutputCharset(),
getStylesheets());
output.beginBody(CssClass.BODY_CONTENT_ABOUT);
printNavBarTop(output, "about");
output.div(CssClass.ABOUT_TITLE, "About");
output.beginDiv(CssClass.ABOUT_GENERATOR);
output.print("Generated by ");
output.print("Gjdoc");
output.print(" HtmlDoclet ");
output.print(getDocletVersion());
output.print(", part of ");
output.beginAnchor("http://www.gnu.org/software/classpath/cp-tools/", "", "_top");
output.print("GNU Classpath Tools");
output.endAnchor();
output.print(", on ");
DateFormat format = DateFormat.getDateTimeInstance(DateFormat.LONG,
DateFormat.LONG,
Locale.US);
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"),
Locale.US);
format.setCalendar(cal);
output.print(format.format(new Date()));
output.print(".");
output.endDiv(CssClass.ABOUT_GENERATOR);
printNavBarBottom(output, "about");
output.endBody();
output.endPage();
output.close();
}
private void printSourcePage(File packageDir, ClassDoc classDoc, String sourceXhtml)
throws IOException
{
HtmlPage output = newHtmlPage(new File(packageDir,
classDoc.name() + "-source" + filenameExtension),
getPathToRoot(packageDir, getTargetDirectory()));
output.beginPage(getPageTitle("Source for " + classDoc.qualifiedTypeName()),
getOutputCharset(),
getStylesheets());
output.beginBody(CssClass.BODY_CONTENT_SOURCE);
printNavBarTop(output, "source", classDoc, null, null);
output.div(CssClass.SOURCE_TITLE, "Source for " + classDoc.qualifiedTypeName());
output.beginDiv(CssClass.SOURCE);
output.print(sourceXhtml);
output.endDiv(CssClass.SOURCE);
printNavBarBottom(output, "source", classDoc);
output.endBody();
output.endPage();
output.close();
}
private void printHelpPage()
throws IOException
{
HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
"help" + filenameExtension),
".");
output.beginPage(getPageTitle("Help"),
getOutputCharset(),
getStylesheets());
output.beginBody(CssClass.BODY_CONTENT_HELP);
printNavBarTop(output, "help");
InputStream helpIn;
if (null != optionHelpFile.getValue()){
helpIn = new FileInputStream(optionHelpFile.getValue());
}
else {
helpIn = getClass().getResourceAsStream("/htmldoclet/help.xhtml");
}
output.insert(new InputStreamReader(helpIn, "utf-8"));
helpIn.close();
printNavBarBottom(output, "help");
output.endBody();
output.endPage();
output.close();
}
private void printOverviewPage()
throws IOException
{
HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
"overview-summary" + filenameExtension),
".");
output.beginPage(getWindowTitle(),
getOutputCharset(),
getStylesheets());
output.beginBody(CssClass.BODY_CONTENT_OVERVIEW);
printNavBarTop(output, "overview");
String overviewHeader;
if (null != optionDocTitle.getValue()) {
overviewHeader = optionDocTitle.getValue();
}
else if (null != optionTitle.getValue()) {
overviewHeader = optionTitle.getValue();
}
else {
overviewHeader = null;
}
if (null != overviewHeader) {
output.div(CssClass.OVERVIEW_TITLE, overviewHeader);
}
output.beginDiv(CssClass.OVERVIEW_DESCRIPTION_TOP);
printTags(output, getRootDoc(), getRootDoc().firstSentenceTags(), true);
output.endDiv(CssClass.OVERVIEW_DESCRIPTION_TOP);
List packageGroups = getPackageGroups();
if (packageGroups.isEmpty()) {
printOverviewPackages(output, getAllPackages(),
"All Packages");
}
else {
Set otherPackages = new LinkedHashSet();
otherPackages.addAll(getAllPackages());
Iterator it = packageGroups.iterator();
while (it.hasNext()) {
PackageGroup packageGroup = (PackageGroup)it.next();
printOverviewPackages(output,
packageGroup.getPackages(),
packageGroup.getName());
otherPackages.removeAll(packageGroup.getPackages());
}
if (!otherPackages.isEmpty()) {
printOverviewPackages(output,
otherPackages,
"Other Packages");
}
}
output.anchorName("description");
output.beginDiv(CssClass.OVERVIEW_DESCRIPTION_FULL);
printTags(output, getRootDoc(), getRootDoc().inlineTags(), false);
output.endDiv(CssClass.OVERVIEW_DESCRIPTION_FULL);
printNavBarBottom(output, "overview");
output.endBody();
output.endPage();
output.close();
}
private void printOverviewPackages(HtmlPage output, Collection packageDocs, String header)
{
output.beginDiv(CssClass.TABLE_CONTAINER);
output.beginTable(CssClass.OVERVIEW_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
output.rowDiv(CssClass.TABLE_HEADER, header);
Iterator it = packageDocs.iterator();
while (it.hasNext()) {
PackageDoc packageDoc = (PackageDoc)it.next();
output.beginRow();
output.beginCell(CssClass.OVERVIEW_SUMMARY_LEFT);
output.beginAnchor(getPackageURL(packageDoc) + "package-summary" + filenameExtension);
output.print(packageDoc.name());
output.endAnchor();
output.endCell();
output.beginCell(CssClass.OVERVIEW_SUMMARY_RIGHT);
printTags(output, packageDoc, packageDoc.firstSentenceTags(), true);
output.endCell();
output.endRow();
}
output.endTable();
output.endDiv(CssClass.TABLE_CONTAINER);
}
private void printClassUsagePage(File packageDir, String pathToRoot, ClassDoc classDoc)
throws IOException
{
HtmlPage output = newHtmlPage(new File(packageDir,
classDoc.name() + "-uses" + filenameExtension),
pathToRoot);
output.beginPage(getPageTitle(classDoc.name()), getOutputCharset(), getStylesheets());
output.beginBody(CssClass.BODY_CONTENT_USES);
printNavBarTop(output, "uses", classDoc, null, null);
output.div(CssClass.USAGE_TITLE,
"Uses of " + getClassTypeName(classDoc)
+ " " + classDoc.qualifiedName());
Map packageToUsageTypeMap = getUsageOfClass(classDoc);
if (null != packageToUsageTypeMap && !packageToUsageTypeMap.isEmpty()) {
Iterator packagesIterator = packageToUsageTypeMap.keySet().iterator();
while (packagesIterator.hasNext()) {
PackageDoc packageDoc = (PackageDoc)packagesIterator.next();
output.div(CssClass.USAGE_PACKAGE_TITLE, "Uses in package " + packageDoc.name());
Map usageTypeToUsersMap = (Map)packageToUsageTypeMap.get(packageDoc);
Iterator usageTypeIterator = usageTypeToUsersMap.keySet().iterator();
while (usageTypeIterator.hasNext()) {
UsageType usageType = (UsageType)usageTypeIterator.next();
output.beginTable(CssClass.USAGE_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
output.rowDiv(CssClass.USAGE_TABLE_HEADER, format("usagetype." + usageType.getId(),
classDoc.qualifiedName()));
Set users = (Set)usageTypeToUsersMap.get(usageType);
Iterator userIterator = users.iterator();
while (userIterator.hasNext()) {
Doc user = (Doc)userIterator.next();
output.beginRow();
if (user instanceof ClassDoc) {
output.beginCell(CssClass.USAGE_SUMMARY_LEFT);
output.print("class");
output.endCell();
output.beginCell(CssClass.USAGE_SUMMARY_RIGHT);
output.beginDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
printType(output, ((ClassDoc)user));
output.endDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
output.beginDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
printTags(output, ((ClassDoc)user), ((ClassDoc)user).firstSentenceTags(), true);
output.endDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
output.endCell();
}
else if (user instanceof FieldDoc) {
FieldDoc fieldDoc = (FieldDoc)user;
output.beginCell(CssClass.USAGE_SUMMARY_LEFT);
printType(output, ((FieldDoc)user).type());
output.endCell();
output.beginCell(CssClass.USAGE_SUMMARY_RIGHT);
output.beginDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
printType(output, ((FieldDoc)user).containingClass());
output.print(".");
output.beginAnchor(getMemberDocURL(output, (FieldDoc)user));
output.print(((FieldDoc)user).name());
output.endAnchor();
output.endDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
output.beginDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
printTags(output, ((FieldDoc)user), ((FieldDoc)user).firstSentenceTags(), true);
output.endDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
output.endCell();
}
else if (user instanceof MethodDoc) {
MethodDoc methodDoc = (MethodDoc)user;
output.beginCell(CssClass.USAGE_SUMMARY_LEFT);
printType(output, ((MethodDoc)user).returnType());
output.endCell();
output.beginCell(CssClass.USAGE_SUMMARY_RIGHT);
output.beginDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
printType(output, ((MethodDoc)user).containingClass());
output.print(".");
output.beginAnchor(getMemberDocURL(output, (MethodDoc)user));
output.print(((MethodDoc)user).name());
output.endAnchor();
printParameters(output, (ExecutableMemberDoc)user);
output.endDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
output.beginDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
printTags(output, ((MethodDoc)user), ((MethodDoc)user).firstSentenceTags(), true);
output.endDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
output.endCell();
}
else if (user instanceof ConstructorDoc) {
ConstructorDoc constructorDoc = (ConstructorDoc)user;
output.beginCell(CssClass.USAGE_SUMMARY_RIGHT);
output.beginDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
printType(output, ((ConstructorDoc)user).containingClass());
output.print(".");
output.beginAnchor(getMemberDocURL(output, (ConstructorDoc)user));
output.print(((ConstructorDoc)user).name());
output.endAnchor();
printParameters(output, (ExecutableMemberDoc)user);
output.endDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
output.beginDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
printTags(output, ((ConstructorDoc)user),
((ConstructorDoc)user).firstSentenceTags(), true);
output.endDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
output.endCell();
}
output.endRow();
}
output.endTable();
}
}
}
else {
output.div(CssClass.USAGE_EMPTY,
getClassTypeName(classDoc)
+ " " + classDoc.qualifiedName() + " is not used by any class in this documentation set.");
}
printNavBarBottom(output, "uses", classDoc);
output.endBody();
output.endPage();
output.close();
}
private void printSuperTreeRec(HtmlPage output, ListIterator it, int level)
{
if (it.hasPrevious()) {
ClassDoc cd = (ClassDoc)it.previous();
output.beginElement("li", new String[] { "class" }, new String[] { "inheritance " + level });
output.beginElement("code");
if (it.hasPrevious()) {
printType(output, cd, true);
}
else {
output.print(cd.qualifiedName() + getTypeParameters(cd));
}
output.endElement("code");
output.endElement("li");
output.beginElement("li");
if (it.hasPrevious()) {
output.beginElement("ul", new String[] { "class" }, new String[] { "inheritance " + (level + 1) });
printSuperTreeRec(output, it, level + 1);
output.endElement("ul");
}
output.endElement("li");
}
}
private static boolean isSubInterface(ClassDoc classDoc, ClassDoc otherClassDoc)
{
ClassDoc[] interfaces = otherClassDoc.interfaces();
for (int i=0; i<interfaces.length; ++i) {
if (classDoc == interfaces[i]) {
return true;
}
else if (isSubInterface(classDoc, interfaces[i])) {
return true;
}
}
return false;
}
private void printCommaSeparatedTypes(HtmlPage output,
Collection list,
String header,
CssClass cssClass)
{
if (!list.isEmpty()) {
output.beginDiv(cssClass);
output.div(CssClass.CLASS_KNOWNIMPLEMENTING_HEADER, header);
output.beginDiv(CssClass.CLASS_KNOWNIMPLEMENTING_ITEM);
Iterator it = list.iterator();
while (it.hasNext()) {
Type type = (Type)it.next();
printType(output, type);
if (it.hasNext()) {
output.print(", ");
}
}
output.endDiv(CssClass.CLASS_KNOWNIMPLEMENTING_ITEM);
output.endDiv(cssClass);
}
}
private void printClassPage(File packageDir, String pathToRoot,
ClassDoc classDoc, ClassDoc prevClassDoc, ClassDoc nextClassDoc)
throws IOException
{
HtmlPage output = newHtmlPage(new File(packageDir,
classDoc.name() + filenameExtension),
pathToRoot);
Set keywords = new LinkedHashSet();
{
keywords.add(classDoc.qualifiedName() + " class");
FieldDoc[] fieldDocs = classDoc.fields();
for (int i=0; i<fieldDocs.length; ++i) {
FieldDoc fieldDoc = fieldDocs[i];
keywords.add(fieldDoc.name());
}
MethodDoc[] methodDocs = classDoc.methods();
for (int i=0; i<methodDocs.length; ++i) {
MethodDoc methodDoc = methodDocs[i];
keywords.add(methodDoc.name() + "()");
}
}
String parameters = getTypeParameters(classDoc);
output.beginPage(getPageTitle(classDoc.name()), getOutputCharset(),
keywords, getStylesheets());
output.beginBody(CssClass.BODY_CONTENT_CLASS);
printNavBarTop(output, "class", classDoc, prevClassDoc, nextClassDoc);
output.beginDiv(CssClass.CLASS_TITLE);
output.div(CssClass.CLASS_TITLE_PACKAGE,
classDoc.containingPackage().name());
output.div(CssClass.CLASS_TITLE_CLASS,
getClassTypeName(classDoc)
+ " " + classDoc.name()
+ parameters);
output.endDiv(CssClass.CLASS_TITLE);
boolean needSep = false;
if (classDoc.isInterface()) {
InterfaceRelation relation
= (InterfaceRelation)getInterfaceRelations().get(classDoc);
printCommaSeparatedTypes(output,
relation.superInterfaces,
"All Superinterfaces:",
CssClass.CLASS_KNOWNIMPLEMENTING);
printCommaSeparatedTypes(output,
relation.subInterfaces,
"Known Subinterfaces:",
CssClass.CLASS_KNOWNIMPLEMENTING);
printCommaSeparatedTypes(output,
relation.implementingClasses,
"Known Implementing Classes:",
CssClass.CLASS_KNOWNIMPLEMENTING);
needSep = !relation.superInterfaces.isEmpty()
|| !relation.subInterfaces.isEmpty()
|| !relation.implementingClasses.isEmpty();
}
else {
needSep = true;
if (!"java.lang.Object".equals(classDoc.qualifiedName())) {
LinkedList superClasses = new LinkedList();
for (ClassDoc cd = classDoc; cd != null; cd = cd.superclass()) {
superClasses.add(cd);
}
output.beginDiv(CssClass.CLASS_INHERITANCETREE);
output.beginElement("ul", new String[] { "class" }, new String[] { "inheritance 0" });
printSuperTreeRec(output, superClasses.listIterator(superClasses.size()), 0);
output.endElement("ul");
output.endDiv(CssClass.CLASS_INHERITANCETREE);
if (null != classDoc.containingClass()) {
output.beginDiv(CssClass.CLASS_ENCLOSINGCLASS);
output.div(CssClass.CLASS_ENCLOSINGCLASS_HEADER, "Enclosing Class:");
output.beginDiv(CssClass.CLASS_ENCLOSINGCLASS_ITEM);
printType(output, classDoc.containingClass());
output.endDiv(CssClass.CLASS_ENCLOSINGCLASS_ITEM);
output.endDiv(CssClass.CLASS_ENCLOSINGCLASS);
}
Set implementedInterfaces = getImplementedInterfaces(classDoc);
printCommaSeparatedTypes(output,
implementedInterfaces,
"Implemented Interfaces:",
CssClass.CLASS_KNOWNIMPLEMENTING);
List knownDirectSubclasses = getKnownDirectSubclasses(classDoc);
if (!knownDirectSubclasses.isEmpty()) {
output.beginDiv(CssClass.CLASS_SUBCLASSES);
output.div(CssClass.CLASS_SUBCLASSES_HEADER, "Known Direct Subclasses:");
output.beginDiv(CssClass.CLASS_SUBCLASSES_ITEM);
Iterator it = knownDirectSubclasses.iterator();
while (it.hasNext()) {
printType(output, (ClassDoc)it.next());
if (it.hasNext()) {
output.print(", ");
}
}
output.endDiv(CssClass.CLASS_SUBCLASSES_ITEM);
output.endDiv(CssClass.CLASS_SUBCLASSES_HEADER);
output.endDiv(CssClass.CLASS_SUBCLASSES);
}
}
}
if (needSep) {
output.hr();
}
output.beginDiv(CssClass.CLASS_SYNOPSIS);
output.beginDiv(CssClass.CLASS_SYNOPSIS_DECLARATION);
output.print(getFullModifiers(classDoc) + ' ' + getClassTypeKeyword(classDoc)
+ ' ');
output.beginSpan(CssClass.CLASS_SYNOPSIS_NAME);
if (optionLinkSource.getValue() && null != classDoc.position()) {
output.beginAnchor(getOuterClassDoc(classDoc).name() + "-source" + filenameExtension + "#line." + classDoc.position());
output.print(classDoc.name() + parameters);
output.endAnchor();
}
else {
output.print(classDoc.name() + parameters);
}
output.endSpan(CssClass.CLASS_SYNOPSIS_NAME);
output.endDiv(CssClass.CLASS_SYNOPSIS_DECLARATION);
if (!classDoc.isInterface()) {
if (null != classDoc.superclass()) {
output.beginDiv(CssClass.CLASS_SYNOPSIS_SUPERCLASS);
output.print("extends ");
printType(output, classDoc.superclass());
output.endDiv(CssClass.CLASS_SYNOPSIS_SUPERCLASS);
}
}
ClassDoc[] interfaces = classDoc.interfaces();
if (interfaces.length > 0) {
output.beginDiv(CssClass.CLASS_SYNOPSIS_IMPLEMENTS);
if (!classDoc.isInterface()) {
output.print("implements ");
}
else {
output.print("extends ");
}
for (int i=0; i<interfaces.length; ++i) {
if (i>0) {
output.print(", ");
}
printType(output, interfaces[i]);
}
output.endDiv(CssClass.CLASS_SYNOPSIS_IMPLEMENTS);
}
output.endDiv(CssClass.CLASS_SYNOPSIS);
output.hr();
if (!optionNoComment.getValue()) {
output.beginDiv(CssClass.CLASS_DESCRIPTION);
printTags(output, classDoc, classDoc.inlineTags(), false);
output.endDiv(CssClass.CLASS_DESCRIPTION);
printTaglets(output, classDoc.tags(), new HtmlTagletContext(classDoc, output, false));
}
Set implementedInterfaces = getImplementedInterfaces(classDoc);
boolean haveInheritedFields = false;
boolean haveInheritedMethods = false;
boolean haveInheritedClasses = false;
{
if (!classDoc.isInterface()) {
ClassDoc superClassDoc = classDoc.superclass();
while (null != superClassDoc
&& (!haveInheritedFields
|| !haveInheritedMethods
|| !haveInheritedClasses)) {
if (superClassDoc.fields().length > 0) {
haveInheritedFields = true;
}
if (superClassDoc.methods().length > 0) {
haveInheritedMethods = true;
}
if (superClassDoc.innerClasses().length > 0) {
haveInheritedClasses = true;
}
superClassDoc = superClassDoc.superclass();
}
}
}
printProgramElementDocs(output, getSortedInnerClasses(classDoc),
"Nested Class Summary", haveInheritedClasses,
"summary-inner");
{
ClassDoc superClassDoc = classDoc.superclass();
while (null != superClassDoc) {
printInheritedMembers(output, getSortedInnerClasses(superClassDoc),
"Nested classes/interfaces inherited from class {0}",
superClassDoc);
superClassDoc = superClassDoc.superclass();
}
}
printProgramElementDocs(output, getSortedFields(classDoc),
"Field Summary", haveInheritedFields,
"summary-fields");
{
ClassDoc superClassDoc = classDoc.superclass();
while (null != superClassDoc) {
printInheritedMembers(output, getSortedFields(superClassDoc),
"Fields inherited from class {0}",
superClassDoc);
superClassDoc = superClassDoc.superclass();
}
}
{
Iterator it = implementedInterfaces.iterator();
while (it.hasNext()) {
ClassDoc implementedInterface
= (ClassDoc)it.next();
if (!"java.io.Serializable".equals(implementedInterface.qualifiedName())
&& !"java.io.Externalizable".equals(implementedInterface.qualifiedName())) {
printInheritedMembers(output, getSortedFields(implementedInterface),
"Fields inherited from interface {0}",
implementedInterface);
}
}
}
printProgramElementDocs(output, getSortedConstructors(classDoc),
"Constructor Summary", false,
"summary-constructors");
printProgramElementDocs(output, getSortedMethods(classDoc),
"Method Summary", haveInheritedMethods,
"summary-methods");
if (classDoc.isInterface()) {
InterfaceRelation relation
= (InterfaceRelation)getInterfaceRelations().get(classDoc);
Iterator it = relation.superInterfaces.iterator();
while (it.hasNext()) {
ClassDoc superClassDoc = (ClassDoc)it.next();
printInheritedMembers(output, getSortedMethods(superClassDoc),
"Methods inherited from interface {0}",
superClassDoc);
}
}
else {
ClassDoc superClassDoc = classDoc.superclass();
while (null != superClassDoc) {
printInheritedMembers(output, getSortedMethods(superClassDoc),
"Methods inherited from class {0}",
superClassDoc);
superClassDoc = superClassDoc.superclass();
}
}
printMemberDetails(output, getSortedFields(classDoc),
"Field Details", false, "detail-fields");
printMemberDetails(output, getSortedConstructors(classDoc),
"Constructor Details", false, "detail-constructors");
printMemberDetails(output, getSortedMethods(classDoc),
"Method Details", false, "detail-methods");
printNavBarBottom(output, "class", classDoc);
output.endBody();
output.endPage();
output.close();
}
private void printInheritedMembers(HtmlPage output,
ProgramElementDoc[] memberDocs,
String headerFormat,
ClassDoc superclass)
{
if (memberDocs.length > 0) {
output.beginDiv(CssClass.TABLE_CONTAINER);
output.beginTable(CssClass.CLASS_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
String superclassLink;
if (superclass.isIncluded()) {
superclassLink = superclass.containingPackage().name()
+ "." + createTypeHref(output, superclass, false);
}
else {
superclassLink = createTypeHref(output, superclass, true);
}
output.rowDiv(CssClass.TABLE_SUB_HEADER,
new MessageFormat(headerFormat).format(new Object[] {
superclassLink
}));
output.beginRow();
output.beginCell(CssClass.CLASS_SUMMARY_INHERITED);
for (int i=0; i<memberDocs.length; ++i) {
ProgramElementDoc memberDoc = memberDocs[i];
if (i > 0) {
output.print(", ");
}
String title = null;
if (memberDoc.isMethod()) {
title = memberDoc.name() + ((MethodDoc)memberDoc).flatSignature();
}
else if (memberDoc.isInterface()) {
title = "interface " + ((ClassDoc)memberDoc).qualifiedName();
}
else if (memberDoc.isClass()) {
title = "class " + ((ClassDoc)memberDoc).qualifiedName();
}
output.beginAnchor(getMemberDocURL(output, memberDoc), title);
output.beginSpan(CssClass.CLASS_SUMMARY_INHERITED_MEMBER);
output.print(memberDoc.name());
output.endSpan(CssClass.CLASS_SUMMARY_INHERITED_MEMBER);
output.endAnchor();
}
output.endCell();
output.endRow();
output.endTable();
output.endDiv(CssClass.TABLE_CONTAINER);
}
}
private void collectSpecifiedByRecursive(Set specifyingInterfaces,
ClassDoc classDoc,
MethodDoc methodDoc)
{
ClassDoc[] interfaces = classDoc.interfaces();
for (int i=0; i<interfaces.length; ++i) {
MethodDoc[] methods = interfaces[i].methods();
for (int j=0; j<methods.length; ++j) {
if (methods[j].name().equals(methodDoc.name())
&& methods[j].signature().equals(methodDoc.signature())) {
specifyingInterfaces.add(methods[j]);
break;
}
}
collectSpecifiedByRecursive(specifyingInterfaces,
interfaces[i],
methodDoc);
}
}
private void printMemberDetails(HtmlPage output,
ProgramElementDoc[] memberDocs, String header,
boolean isOnSerializedPage,
String anchor)
{
if (memberDocs.length > 0) {
if (null != anchor) {
output.anchorName(anchor);
}
CssClass sectionClass;
CssClass headerClass;
if (isOnSerializedPage) {
sectionClass = CssClass.SERIALIZED_SECTION;
headerClass = CssClass.SERIALIZED_SECTION_HEADER;
}
else {
sectionClass = CssClass.SECTION;
headerClass = CssClass.SECTION_HEADER;
}
output.div(headerClass, header);
output.beginDiv(sectionClass);
for (int i=0; i<memberDocs.length; ++i) {
if (i>0) {
output.hr();
}
ProgramElementDoc memberDoc = memberDocs[i];
output.anchorName(getMemberAnchor(memberDoc));
output.beginDiv(CssClass.MEMBER_DETAIL);
output.div(CssClass.MEMBER_DETAIL_NAME, memberDoc.name());
StringBuffer synopsis = new StringBuffer();
int synopsisLength = 0;
if (!isOnSerializedPage || !memberDoc.isField()) {
String fullModifiers = getFullModifiers(memberDoc);
synopsis.append(fullModifiers);
synopsisLength += fullModifiers.length();
}
if (memberDoc.isMethod() || memberDoc.isField()) {
Type type;
if (memberDoc.isMethod()) {
type = ((MethodDoc)memberDoc).returnType();
}
else {
type = ((FieldDoc)memberDoc).type();
}
synopsis.append(" ");
synopsisLength ++;
synopsis.append(createTypeHref(output, type, false));
if (null != type.asClassDoc() && type.asClassDoc().isIncluded()) {
synopsisLength += type.asClassDoc().name().length();
}
else {
synopsisLength += type.qualifiedTypeName().length();
}
synopsisLength += type.dimension().length();
}
synopsis.append(" ");
synopsisLength ++;
if (optionLinkSource.getValue() && null != memberDoc.position()) {
ClassDoc containingClass = memberDoc.containingClass();
while (null != containingClass.containingClass()) {
containingClass = containingClass.containingClass();
}
String href = containingClass.name() + "-source" + filenameExtension + "#line." + memberDoc.position().line();
synopsis.append(output.createHrefString(href, memberDoc.name()));
}
else {
synopsis.append(memberDoc.name());
}
synopsisLength += memberDoc.name().length();
if (memberDoc.isConstructor() || memberDoc.isMethod()) {
//printParameters(output, (ExecutableMemberDoc)memberDoc);
synopsis.append("(");
++ synopsisLength;
StringBuffer paddingLeft = new StringBuffer();
for (int j=0; j<synopsisLength; ++j) {
paddingLeft.append(' ');
}
Parameter[] parameters = ((ExecutableMemberDoc)memberDoc).parameters();
for (int j=0; j<parameters.length; ++j) {
Parameter parameter = parameters[j];
synopsis.append(createTypeHref(output, parameter.type(), false));
synopsis.append(" ");
synopsis.append(parameter.name());
if (j < parameters.length - 1) {
synopsis.append(",\n");
synopsis.append(paddingLeft);
}
}
synopsis.append(")");
ClassDoc[] exceptions = ((ExecutableMemberDoc)memberDoc).thrownExceptions();
if (exceptions.length > 0) {
synopsis.append("\n throws ");
for (int j=0; j<exceptions.length; ++j) {
ClassDoc exception = exceptions[j];
synopsis.append(createTypeHref(output, exception, false));
if (j < exceptions.length - 1) {
synopsis.append(",\n ");
}
}
}
}
output.beginDiv(CssClass.MEMBER_DETAIL_SYNOPSIS);
output.print(synopsis.toString());
output.endDiv(CssClass.MEMBER_DETAIL_SYNOPSIS);
output.beginDiv(CssClass.MEMBER_DETAIL_BODY);
Tag[] deprecatedTags = memberDoc.tags("deprecated");
if (deprecatedTags.length > 0) {
output.beginDiv(CssClass.DEPRECATED_INLINE);
output.beginSpan(CssClass.DEPRECATED_HEADER);
output.print("Deprecated. ");
output.endSpan(CssClass.DEPRECATED_HEADER);
output.beginSpan(CssClass.DEPRECATED_BODY);
}
for (int j=0; j<deprecatedTags.length; ++j) {
printTags(output, memberDoc, deprecatedTags[j].inlineTags(), true);
}
if (deprecatedTags.length > 0) {
output.endSpan(CssClass.DEPRECATED_BODY);
output.beginDiv(CssClass.DEPRECATED_INLINE);
}
output.beginDiv(CssClass.MEMBER_DETAIL_DESCRIPTION);
printTags(output, memberDoc, memberDoc.inlineTags(), false);
output.endDiv(CssClass.MEMBER_DETAIL_DESCRIPTION);
if (memberDoc.isConstructor() || memberDoc.isMethod()) {
if (memberDoc.isMethod()) {
Set specifyingInterfaces = new LinkedHashSet();
if (memberDoc.containingClass().isInterface()) {
collectSpecifiedByRecursive(specifyingInterfaces,
memberDoc.containingClass(),
(MethodDoc)memberDoc);
}
else {
for (ClassDoc cd = memberDoc.containingClass();
null != cd; cd = cd.superclass()) {
collectSpecifiedByRecursive(specifyingInterfaces,
cd,
(MethodDoc)memberDoc);
}
}
if (!specifyingInterfaces.isEmpty()
&& !isOnSerializedPage) {
output.beginDiv(CssClass.MEMBER_DETAIL_SPECIFIED_BY_LIST);
output.div(CssClass.MEMBER_DETAIL_SPECIFIED_BY_HEADER, "Specified by:");
Iterator it = specifyingInterfaces.iterator();
while (it.hasNext()) {
MethodDoc specifyingInterfaceMethod = (MethodDoc)it.next();
output.beginDiv(CssClass.MEMBER_DETAIL_SPECIFIED_BY_ITEM);
output.beginAnchor(getMemberDocURL(output,
specifyingInterfaceMethod));
output.print(memberDoc.name());
output.endAnchor();
output.print(" in interface ");
printType(output, specifyingInterfaceMethod.containingClass());
output.endDiv(CssClass.MEMBER_DETAIL_SPECIFIED_BY_ITEM);
}
output.endDiv(CssClass.MEMBER_DETAIL_SPECIFIED_BY_LIST);
}
ClassDoc overriddenClassDoc = null;
MemberDoc specifyingSuperMethod = null;
for (ClassDoc superclassDoc = memberDoc.containingClass().superclass();
null != superclassDoc && null == overriddenClassDoc;
superclassDoc = superclassDoc.superclass()) {
MethodDoc[] methods = superclassDoc.methods();
for (int j=0; j<methods.length; ++j) {
if (methods[j].name().equals(memberDoc.name())
&& methods[j].signature().equals(((MethodDoc)memberDoc).signature())) {
overriddenClassDoc = superclassDoc;
specifyingSuperMethod = methods[j];
break;
}
}
}
if (null != overriddenClassDoc) {
output.beginDiv(CssClass.MEMBER_DETAIL_OVERRIDDEN_LIST);
output.div(CssClass.MEMBER_DETAIL_OVERRIDDEN_HEADER, "Overrides:");
output.beginDiv(CssClass.MEMBER_DETAIL_OVERRIDDEN_ITEM);
output.beginAnchor(getMemberDocURL(output,
specifyingSuperMethod));
output.print(memberDoc.name());
output.endAnchor();
output.print(" in interface ");
printType(output, overriddenClassDoc);
output.endDiv(CssClass.MEMBER_DETAIL_OVERRIDDEN_ITEM);
output.endDiv(CssClass.MEMBER_DETAIL_OVERRIDDEN_LIST);
}
}
if (!optionNoComment.getValue()) {
ExecutableMemberDoc execMemberDoc
= (ExecutableMemberDoc)memberDoc;
if (execMemberDoc.paramTags().length > 0) {
output.beginDiv(CssClass.MEMBER_DETAIL_PARAMETER_LIST);
output.div(CssClass.MEMBER_DETAIL_PARAMETER_HEADER, "Parameters:");
Parameter[] parameters = execMemberDoc.parameters();
for (int j=0; j<parameters.length; ++j) {
Parameter parameter = parameters[j];
ParamTag[] paramTags = execMemberDoc.paramTags();
ParamTag paramTag = null;
for (int k=0; k<paramTags.length; ++k) {
if (paramTags[k].parameterName().equals(parameter.name())) {
paramTag = paramTags[k];
break;
}
}
if (null != paramTag) {
output.beginDiv(CssClass.MEMBER_DETAIL_PARAMETER_ITEM);
output.beginSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_NAME);
output.print(parameter.name());
output.endSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_NAME);
output.beginSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_SEPARATOR);
output.print(" - ");
output.endSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_SEPARATOR);
output.beginSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_DESCRIPTION);
printTags(output, execMemberDoc, paramTag.inlineTags(), false);
output.endSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_DESCRIPTION);
output.endDiv(CssClass.MEMBER_DETAIL_PARAMETER_ITEM);
}
}
output.endDiv(CssClass.MEMBER_DETAIL_PARAMETER_LIST);
}
if (execMemberDoc.isMethod()
&& !"void".equals(((MethodDoc)execMemberDoc).returnType().typeName())) {
Tag[] returnTags = execMemberDoc.tags("return");
if (returnTags.length > 0) {
Tag returnTag = returnTags[0];
output.beginDiv(CssClass.MEMBER_DETAIL_RETURN_LIST);
output.div(CssClass.MEMBER_DETAIL_RETURN_HEADER, "Returns:");
output.beginDiv(CssClass.MEMBER_DETAIL_RETURN_ITEM);
printTags(output, execMemberDoc, returnTag.inlineTags(), false);
output.endDiv(CssClass.MEMBER_DETAIL_RETURN_ITEM);
output.endDiv(CssClass.MEMBER_DETAIL_RETURN_LIST);
}
}
Set thrownExceptions = getThrownExceptions(execMemberDoc);
boolean haveThrowsInfo = false;
ThrowsTag[] throwsTags = execMemberDoc.throwsTags();
for (int k=0; k<throwsTags.length; ++k) {
ThrowsTag throwsTag = throwsTags[k];
if (null != throwsTags[k].exception()
&& (isUncheckedException(throwsTags[k].exception())
|| thrownExceptions.contains(throwsTag.exception()))) {
haveThrowsInfo = true;
break;
}
}
if (haveThrowsInfo) {
output.beginDiv(CssClass.MEMBER_DETAIL_THROWN_LIST);
output.div(CssClass.MEMBER_DETAIL_THROWN_HEADER, "Throws:");
for (int k=0; k<throwsTags.length; ++k) {
ThrowsTag throwsTag = throwsTags[k];
if (null != throwsTag.exception()
&& (isUncheckedException(throwsTag.exception())
|| thrownExceptions.contains(throwsTag.exception()))) {
output.beginDiv(CssClass.MEMBER_DETAIL_THROWN_ITEM);
output.beginSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_NAME);
printType(output, throwsTags[k].exception());
output.endSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_NAME);
if (null != throwsTag) {
output.beginSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_SEPARATOR);
output.print(" - ");
output.endSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_SEPARATOR);
output.beginSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_DESCRIPTION);
printTags(output, execMemberDoc, throwsTag.inlineTags(), false);
output.endSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_DESCRIPTION);
}
output.endDiv(CssClass.MEMBER_DETAIL_THROWN_ITEM);
}
}
output.endDiv(CssClass.MEMBER_DETAIL_THROWN_LIST);
}
}
}
if (!optionNoComment.getValue()) {
if (memberDoc.isField()) {
FieldDoc fieldDoc = ((FieldDoc)memberDoc);
if (null != fieldDoc.constantValue()) {
output.beginDiv(CssClass.MEMBER_DETAIL_THROWN_LIST);
output.div(CssClass.MEMBER_DETAIL_THROWN_HEADER, "Field Value:");
output.div(CssClass.MEMBER_DETAIL_THROWN_ITEM,
fieldDoc.constantValueExpression().toString());
output.endDiv(CssClass.MEMBER_DETAIL_THROWN_LIST);
}
}
TagletContext context = new HtmlTagletContext(memberDoc, output, isOnSerializedPage);
printTaglets(output, memberDoc.tags(), context);
}
output.endDiv(CssClass.MEMBER_DETAIL_BODY);
output.endDiv(CssClass.MEMBER_DETAIL);
}
output.endDiv(sectionClass);
}
}
private void printParameters(HtmlPage output, ExecutableMemberDoc memberDoc)
{
Parameter[] parameters = memberDoc.parameters();
output.print("(");
for (int j=0; j<parameters.length; ++j) {
if (j > 0) {
output.print(", ");
}
printType(output, parameters[j].type());
output.print("&nbsp;");
output.print(parameters[j].name());
}
output.print(")");
}
private void printProgramElementDocs(HtmlPage output,
ProgramElementDoc[] memberDocs,
String header,
boolean forceOutputHeader,
String anchor)
{
if (memberDocs.length > 0 || forceOutputHeader) {
output.anchorName(anchor);
output.beginDiv(CssClass.TABLE_CONTAINER);
output.beginTable(CssClass.CLASS_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
output.rowDiv(CssClass.TABLE_HEADER, header);
for (int i=0; i<memberDocs.length; ++i) {
ProgramElementDoc memberDoc = memberDocs[i];
output.beginRow();
if (!memberDoc.isConstructor()) {
output.beginCell(CssClass.CLASS_SUMMARY_LEFT);
output.beginDiv(CssClass.CLASS_SUMMARY_LEFT_SYNOPSIS);
output.print(getSummaryModifiers(memberDoc) + " ");
if (memberDoc.isMethod()) {
printType(output, ((MethodDoc)memberDoc).returnType());
}
else if (memberDoc.isField()) {
printType(output, ((FieldDoc)memberDoc).type());
}
else if (memberDoc.isInterface()) {
output.print(" interface");
}
else if (memberDoc.isClass()) {
output.print(" class");
}
output.endDiv(CssClass.CLASS_SUMMARY_LEFT_SYNOPSIS);
output.endCell();
}
output.beginCell(CssClass.CLASS_SUMMARY_RIGHT);
output.beginDiv(CssClass.CLASS_SUMMARY_RIGHT_LIST);
output.beginDiv(CssClass.CLASS_SUMMARY_RIGHT_SYNOPSIS);
if (memberDoc.isClass() || memberDoc.isInterface()) {
output.beginAnchor(getClassDocURL(output, (ClassDoc)memberDoc));
}
else {
output.beginAnchor("#" + getMemberAnchor(memberDoc));
}
output.print(memberDoc.name());
output.endAnchor();
if (memberDoc.isConstructor() || memberDoc.isMethod()) {
printParameters(output, (ExecutableMemberDoc)memberDoc);
}
output.endDiv(CssClass.CLASS_SUMMARY_RIGHT_SYNOPSIS);
Tag[] firstSentenceTags;
Tag[] deprecatedTags = memberDoc.tags("deprecated");
if (deprecatedTags.length > 0) {
firstSentenceTags = deprecatedTags[0].firstSentenceTags();
}
else {
firstSentenceTags = memberDoc.firstSentenceTags();
}
if (null != firstSentenceTags && firstSentenceTags.length > 0) {
output.beginDiv(CssClass.CLASS_SUMMARY_RIGHT_DESCRIPTION);
if (deprecatedTags.length > 0) {
output.beginDiv(CssClass.DEPRECATED);
output.beginSpan(CssClass.DEPRECATED_HEADER);
output.print("Deprecated. ");
output.endSpan(CssClass.DEPRECATED_HEADER);
output.beginSpan(CssClass.DEPRECATED_BODY);
}
printTags(output, memberDoc, firstSentenceTags, true);
if (deprecatedTags.length > 0) {
output.endSpan(CssClass.DEPRECATED_BODY);
output.beginDiv(CssClass.DEPRECATED);
}
output.endDiv(CssClass.CLASS_SUMMARY_RIGHT_DESCRIPTION);
}
output.endDiv(CssClass.CLASS_SUMMARY_RIGHT_LIST);
output.endCell();
output.endRow();
}
output.endTable();
output.endDiv(CssClass.TABLE_CONTAINER);
}
}
private void printTag(final HtmlPage output,
HtmlRepairer repairer,
Tag tag, boolean firstSentence,
boolean inline,
Doc contextDoc)
{
TagletContext context = new HtmlTagletContext(contextDoc, output, false);
if (firstSentence) {
output.print(renderInlineTags(tag.firstSentenceTags(), context));
}
else {
output.print(renderInlineTags(tag.inlineTags(), context));
}
}
private void printTags(HtmlPage output, Doc contextDoc, Tag[] tags, boolean firstSentence)
{
printTags(output, contextDoc, tags, firstSentence, false);
}
private void printTags(HtmlPage output, Doc contextDoc, Tag[] tags, boolean firstSentence, boolean inline)
{
if (!optionNoComment.getValue()) {
output.print(renderInlineTags(tags, new HtmlTagletContext(contextDoc, output, false)));
}
/*
if (!optionNoComment.getValue()) {
output.print(renderInlineTags(tag.firstSentenceTags(), output));
HtmlRepairer repairer = new HtmlRepairer(getRootDoc(),
true, false,
null, null,
true);
for (int i=0; i<tags.length; ++i) {
printTag(output, repairer, tags[i], firstSentence, inline);
}
output.print(repairer.terminateText());
}
*/
}
private String getClassDocURL(HtmlPage output, ClassDoc classDoc)
{
return output.getPathToRoot()
+ "/"
+ getPackageURL(classDoc.containingPackage())
+ classDoc.name() + filenameExtension;
}
private String getMemberDocURL(HtmlPage output, ProgramElementDoc memberDoc)
{
ClassDoc classDoc = memberDoc.containingClass();
PackageDoc packageDoc = classDoc.containingPackage();
ExternalDocSet externalDocSet = null;
if (classDoc.containingPackage().name().length() > 0) {
externalDocSet = (ExternalDocSet)packageNameToDocSet.get(packageDoc.name());
}
StringBuffer result = new StringBuffer();
result.append(getClassDocURL(output, classDoc));
result.append('#');
if (null == externalDocSet) {
result.append(getMemberAnchor(memberDoc));
}
else {
result.append(getMemberAnchor(memberDoc, externalDocSet.isJavadocCompatible()));
}
return result.toString();
}
private void printType(HtmlPage output, Type type)
{
printType(output, type, false);
}
private void printType(HtmlPage output, Type type, boolean fullyQualified)
{
output.print(createTypeHref(output, type, fullyQualified));
}
private String createTypeHref(HtmlPage output, Type type, boolean fullyQualified)
{
ClassDoc asClassDoc = type.asClassDoc();
String url = null;
if (null != asClassDoc && asClassDoc.isIncluded()) {
url = getClassDocURL(output, asClassDoc);
}
else if (!type.isPrimitive()) {
if (type.qualifiedTypeName().length() > type.typeName().length()) {
String packageName = type.qualifiedTypeName();
packageName = packageName.substring(0, packageName.length() - type.typeName().length() - 1);
ExternalDocSet externalDocSet
= (ExternalDocSet)packageNameToDocSet.get(packageName);
if (null != externalDocSet) {
url = externalDocSet.getClassDocURL(packageName, type.typeName());
}
}
}
StringBuffer result = new StringBuffer();
if (null != url && null != asClassDoc) {
String parameters = getTypeParameters(asClassDoc);
if (fullyQualified) {
result.append(output.createHrefString(url,possiblyQualifiedName(asClassDoc) + parameters));
}
else {
StringBuffer title = new StringBuffer();
title.append(getClassTypeName(asClassDoc));
title.append(" in ");
title.append(asClassDoc.containingPackage().name());
result.append(output.createHrefString(url, asClassDoc.name() + parameters, title.toString()));
}
}
else {
result.append(possiblyQualifiedName(type));
}
result.append(type.dimension());
return result.toString();
}
private void printTaglets(final HtmlPage output, Tag[] tags, TagletContext context)
{
super.printMainTaglets(tags, context, new TagletPrinter() {
public void printTagletString(String tagletString) {
output.beginDiv(CssClass.TAGLET);
output.print(tagletString);
output.endDiv(CssClass.TAGLET);
}
});
}
private String getPackageURL(PackageDoc packageDoc)
{
if (packageDoc.name().length() > 0) {
ExternalDocSet externalDocSet = (ExternalDocSet)packageNameToDocSet.get(packageDoc.name());
String url;
if (null != externalDocSet) {
url = externalDocSet.getPackageDocURL(packageDoc.name());
}
else {
url = packageDoc.name().replace('.', '/');
}
if (!url.endsWith("/")) {
return url + '/';
}
else {
return url;
}
}
else {
return "";
}
}
private String getClassURL(ClassDoc classDoc)
{
ExternalDocSet externalDocSet = null;
if (classDoc.containingPackage().name().length() > 0) {
externalDocSet = (ExternalDocSet)packageNameToDocSet.get(classDoc.containingPackage().name());
}
if (null != externalDocSet) {
return externalDocSet.getClassDocURL(classDoc.containingPackage().name(),
classDoc.name());
}
else {
return getPackageURL(classDoc.containingPackage()) + classDoc.name() + filenameExtension;
}
}
protected void run()
throws DocletConfigurationException, IOException
{
if (optionSerialWarn.getValue()) {
printWarning("Option -serialwarn is currently ignored.");
}
if (null != optionTitle.getValue()) {
printWarning("Option -title is deprecated.");
}
if (!optionValidHtml.getValue()) {
printWarning("Option -validhtml hasn't been specified. Generated HTML will not validate.");
}
{
boolean warningEmitted = false;
Iterator it = externalDocSets.iterator();
while (it.hasNext()) {
ExternalDocSet externalDocSet = (ExternalDocSet)it.next();
printNotice("Fetching package list for external documentation set.");
try {
externalDocSet.load(getTargetDirectory());
if (!isJavadocCompatibleNames() && externalDocSet.isJavadocCompatible()
&& !warningEmitted) {
printWarning("Linking to javadoc-compatible documentation. Generated HTML will not validate ");
warningEmitted = true;
}
}
catch (FileNotFoundException e) {
printWarning("Cannot fetch package list from " + externalDocSet.getPackageListDir());
}
Iterator pit = externalDocSet.getPackageNames().iterator();
while (pit.hasNext()) {
String packageName = (String)pit.next();
packageNameToDocSet.put(packageName, externalDocSet);
}
}
}
printNotice("Building cross-reference information...");
getInterfaceRelations();
getAllSubClasses();
printNotice("Writing overview files...");
printFrameSetPage();
if (!isSinglePackage()) {
printPackagesMenuPage();
printAllClassesMenuPage();
printOverviewPage();
if (!optionNoTree.getValue()) {
printNotice("Writing full tree...");
printFullTreePage();
}
}
printPackagesListFile();
printAboutPage();
if (!optionNoIndex.getValue()) {
printNotice("Writing index...");
if (!optionSplitIndex.getValue()) {
printIndexPage();
}
else {
printSplitIndex();
}
}
if (outputHelpPage && !optionNoHelp.getValue()) {
printHelpPage();
}
// Copy resources
File resourcesDir = new File(getTargetDirectory(),
"resources");
if ((resourcesDir.exists() && !resourcesDir.isDirectory())
|| (!resourcesDir.exists() && !resourcesDir.mkdirs())) {
throw new IOException("Cannot create directory " + resourcesDir);
}
// Copy resources
String[] resourceNames = {
"gjdoc.js",
"gjdochtml-clean-layout.css",
"gjdochtml-clean-color1.css",
"inherit.png",
"xhtml11-target10.dtd",
};
for (int i=0; i<resourceNames.length; ++i) {
String resourceName = resourceNames[i];
File targetFile = new File(resourcesDir,
resourceName);
InputStream in = getClass().getResourceAsStream("/htmldoclet/" + resourceName);
if (in == null) {
in = new FileInputStream("src/resources/htmldoclet/" + resourceName);
}
FileOutputStream out = new FileOutputStream(targetFile);
IOToolkit.copyStream(in, out);
in.close();
out.close();
}
// Copy stylesheets
if (null != optionAddStylesheet.getValue()) {
File addStylesheetTargetFile = new File(resourcesDir,
"user.css");
IOToolkit.copyFile(optionAddStylesheet.getValue(),
addStylesheetTargetFile);
}
if (null != optionStylesheetFile.getValue()) {
File stylesheetTargetFile = new File(resourcesDir,
"user.css");
IOToolkit.copyFile(optionStylesheetFile.getValue(),
stylesheetTargetFile);
}
// Write gjdoc.properties
File gjdocPropertiesTargetFile = new File(getTargetDirectory(),
"gjdoc.properties");
writeGjdocProperties(gjdocPropertiesTargetFile);
/*
else {
InputStream cssIn = getClass().getResourceAsStream("/htmldoclet/gjdochtml-vanilla.css");
FileOutputStream cssOut = new FileOutputStream(stylesheetTargetFile);
IOToolkit.copyStream(cssIn, cssOut);
cssIn.close();
cssOut.close();
}
*/
if (!optionNoDeprecatedList.getValue()) {
printDeprecationPage();
}
printSerializationPage();
Collection packageDocsCollection = getAllPackages();
PackageDoc[] packageDocs
= (PackageDoc[])packageDocsCollection.toArray(new PackageDoc[0]);
for (int i=0; i<packageDocs.length; ++i) {
PackageDoc packageDoc = packageDocs[i];
File packageDir = new File(getTargetDirectory(),
packageDoc.name().replace('.', File.separatorChar));
if (!packageDir.exists() && !packageDir.mkdirs()) {
throw new IOException("Couldn't create directory " + packageDir);
}
try {
List packageSourceDirs = getPackageSourceDirs(packageDoc);
Iterator pdIt = packageSourceDirs.iterator();
while (pdIt.hasNext()) {
File sourcePackageDir = (File)pdIt.next();
copyDocFiles(sourcePackageDir, packageDir);
}
}
catch (IOException ignore) {
}
String pathToRoot = getPathToRoot(packageDir, getTargetDirectory());
String packageName = packageDoc.name();
if (0 == packageName.length()) {
packageName = "<unnamed>";
}
printNotice("Writing HTML files for package " + packageName);
printPackagePage(packageDir, pathToRoot, packageDoc,
(i > 0) ? packageDocs[i - 1] : null,
(i < packageDocs.length - 1) ? packageDocs[i + 1] : null);
if (!optionNoTree.getValue()) {
printPackageTreePage(packageDir, pathToRoot, packageDoc);
}
printPackageClassesMenuPage(packageDir, pathToRoot, packageDoc);
ClassDoc[] classDocs = packageDoc.allClasses();
for (int j=0; j<classDocs.length; ++j) {
ClassDoc classDoc = classDocs[j];
if (classDoc.isIncluded()) {
printClassPage(packageDir, pathToRoot,
classDocs[j],
(j > 0) ? classDocs[j - 1] : null,
(j < classDocs.length - 1) ? classDocs[j + 1] : null
);
if (optionUse.getValue()) {
printClassUsagePage(packageDir, pathToRoot, classDocs[j]);
}
if (optionLinkSource.getValue() && null == classDoc.containingClass()) {
try {
File sourceFile = getSourceFile(classDoc);
Java2xhtml java2xhtml = new Java2xhtml();
Properties properties = new Properties();
properties.setProperty("isCodeSnippet", "true");
properties.setProperty("hasLineNumbers", "true");
java2xhtml.setProperties(properties);
StringWriter sourceBuffer = new StringWriter();
FileReader sourceReader = new FileReader(sourceFile);
IOToolkit.copyStream(sourceReader, sourceBuffer);
sourceReader.close();
String result = java2xhtml.makeHTML(sourceBuffer.getBuffer(), sourceFile.getName());
printSourcePage(packageDir,
classDoc,
result);
}
catch (IOException e) {
printWarning("Cannot locate source file for class " + classDoc.qualifiedTypeName());
}
}
}
}
}
}
private String getPathToRoot(File subDir, File rootDir)
{
StringBuffer result = new StringBuffer();
while (!subDir.equals(rootDir)) {
if (result.length() > 0) {
result.append("/");
}
subDir = subDir.getParentFile();
result.append("..");
}
if (0 == result.length()) {
result.append(".");
}
return result.toString();
}
private String getClassTypeName(ClassDoc classDoc)
{
if (classDoc.isInterface()) {
return "Interface";
}
else {
return "Class";
}
}
private String getClassTypeKeyword(ClassDoc classDoc)
{
if (classDoc.isInterface()) {
return "interface";
}
else {
return "class";
}
}
private String getMemberAnchor(ProgramElementDoc memberDoc)
{
return getMemberAnchor(memberDoc, isJavadocCompatibleNames());
}
private String getMemberAnchor(ProgramElementDoc memberDoc, boolean javadocCompatibility)
{
StringBuffer anchor = new StringBuffer();
anchor.append(memberDoc.name());
if (memberDoc.isConstructor() || memberDoc.isMethod()) {
if (javadocCompatibility) {
anchor.append(((ExecutableMemberDoc)memberDoc).signature());
}
else {
anchor.append(':');
Parameter[] parameters = ((ExecutableMemberDoc)memberDoc).parameters();
for (int i=0; i<parameters.length; ++i) {
anchor.append(parameters[i].type().typeName());
for (int j=0; j<parameters[i].type().dimension().length()/2; ++j) {
anchor.append('-');
}
if (i < parameters.length - 1) {
anchor.append(':');
}
}
}
}
return anchor.toString();
}
private String getFullModifiers(ProgramElementDoc memberDoc)
{
StringBuffer result = new StringBuffer();
if (memberDoc.isPackagePrivate()) {
result.append("(package private) ");
}
result.append(memberDoc.modifiers());
if ((memberDoc.isClass() && ((ClassDoc)memberDoc).isAbstract())
|| (memberDoc.isMethod() && ((MethodDoc)memberDoc).isAbstract())) {
result.append(" abstract");
}
return result.toString();
}
private String getSummaryModifiers(ProgramElementDoc memberDoc)
{
StringBuffer result = new StringBuffer();
if (memberDoc.isPackagePrivate()) {
result.append("(package private) ");
}
else if (memberDoc.isPrivate()) {
result.append("private ");
}
else if (memberDoc.isProtected()) {
result.append("protected ");
}
if (memberDoc.isStatic()) {
result.append("static");
}
else if ((memberDoc.isClass() && ((ClassDoc)memberDoc).isAbstract())
|| (memberDoc.isMethod() && ((MethodDoc)memberDoc).isAbstract())) {
result.append("abstract");
}
return result.toString();
}
protected DocletOption[] getOptions()
{
return options;
}
private DocletOptionFlag optionNoNavBar =
new DocletOptionFlag("-nonavbar");
private DocletOptionFlag optionNoTree =
new DocletOptionFlag("-notree");
private DocletOptionFlag optionNoDeprecatedList =
new DocletOptionFlag("-nodeprecatedlist");
private DocletOptionFlag optionNoIndex =
new DocletOptionFlag("-noindex");
private DocletOptionFlag optionUse =
new DocletOptionFlag("-use");
private DocletOptionFlag optionNoHelp =
new DocletOptionFlag("-nohelp");
private DocletOptionFlag optionNoComment =
new DocletOptionFlag("-nocomment");
private DocletOptionFlag optionSerialWarn =
new DocletOptionFlag("-serialwarn");
private DocletOptionFlag optionSplitIndex =
new DocletOptionFlag("-splitindex");
private DocletOptionString optionHeader =
new DocletOptionString("-header");
private DocletOptionString optionFooter =
new DocletOptionString("-footer");
private DocletOptionString optionBottom =
new DocletOptionString("-bottom");
private DocletOptionString optionWindowTitle =
new DocletOptionString("-windowtitle");
private DocletOptionString optionDocTitle =
new DocletOptionString("-doctitle");
private DocletOptionString optionTitle =
new DocletOptionString("-title");
private DocletOptionFile optionHelpFile =
new DocletOptionFile("-helpfile");
private DocletOptionFile optionStylesheetFile =
new DocletOptionFile("-stylesheetfile");
private DocletOptionFlag optionLinkSource =
new DocletOptionFlag("-linksource");
private DocletOption optionLink =
new DocletOption("-link") {
public int getLength()
{
return 2;
}
public boolean set(String[] optionArr)
{
externalDocSets.add(new ExternalDocSet(optionArr[1], null));
return true;
}
};
private DocletOption optionLinkOffline =
new DocletOption("-linkoffline") {
public int getLength()
{
return 3;
}
public boolean set(String[] optionArr)
{
externalDocSets.add(new ExternalDocSet(optionArr[1], optionArr[2]));
return true;
}
};
private DocletOptionString optionDocEncoding =
new DocletOptionString("-docencoding");
private DocletOptionString optionEncoding =
new DocletOptionString("-encoding");
private DocletOptionString optionCharset =
new DocletOptionString("-charset");
private DocletOptionFile optionAddStylesheet =
new DocletOptionFile("-addstylesheet");
private DocletOptionFlag optionValidHtml =
new DocletOptionFlag("-validhtml");
private DocletOptionString optionBaseUrl =
new DocletOptionString("-baseurl");
private DocletOption[] options =
{
optionNoNavBar,
optionNoTree,
optionNoDeprecatedList,
optionNoIndex,
optionNoHelp,
optionNoComment,
optionUse,
optionSplitIndex,
optionHeader,
optionFooter,
optionBottom,
optionHelpFile,
optionStylesheetFile,
optionWindowTitle,
optionDocTitle,
optionTitle,
optionLinkSource,
optionLink,
optionLinkOffline,
optionDocEncoding,
optionEncoding,
optionCharset,
optionAddStylesheet,
optionValidHtml,
optionBaseUrl,
};
static {
setInstance(new HtmlDoclet());
}
private static String replaceDocRoot(HtmlPage output, String str)
{
return StringToolkit.replace(str, "{@docRoot}", output.getPathToRoot());
}
private String getOutputDocEncoding()
{
String encoding = optionDocEncoding.getValue();
if (null == encoding) {
encoding = optionEncoding.getValue();
}
return encoding;
}
private String getOutputCharset()
{
if (null == outputCharset) {
if (null != optionCharset.getValue()) {
outputCharset = optionCharset.getValue();
}
else {
String fileEncoding = System.getProperty("file.encoding");
if (null != fileEncoding) {
try {
outputCharset = Charset.forName(fileEncoding).name();
}
catch (Exception ignore) {
}
}
if (null == outputCharset) {
printWarning("Cannot determine platform default charset, falling back to ISO-8859-1.");
outputCharset = "ISO-8859-1";
}
}
}
return outputCharset;
}
public InlineTagRenderer getInlineTagRenderer()
{
return this;
}
public String renderInlineTags(Tag[] tags, TagletContext context)
{
StringBuffer result = new StringBuffer();
HtmlRepairer repairer = new HtmlRepairer(getRootDoc(),
true, false,
null, null,
true);
for (int i=0; i<tags.length; ++i) {
Tag tag = tags[i];
if ("Text".equals(tag.name())) {
result.append(repairer.getWellformedHTML(tag.text()));
}
else if ("@link".equals(tag.name())) {
result.append(renderSeeTag((SeeTag)tag, context, false));
}
else if ("@linkplain".equals(tag.name())) {
result.append(renderSeeTag((SeeTag)tag, context, true));
}
else if ("@docRoot".equals(tag.name())) {
result.append(((HtmlTagletContext)context).getOutput().getPathToRoot());
}
else {
//TagletContext context = TagletContext.OVERVIEW; // FIXME
Taglet taglet = (Taglet)tagletMap.get(tag.name().substring(1));
if (null != taglet) {
if (taglet instanceof GnuExtendedTaglet) {
result.append(((GnuExtendedTaglet)taglet).toString(tag, context));
}
else {
result.append(taglet.toString(tag));
}
}
}
}
result.append(repairer.terminateText());
return result.toString();
}
public String renderSeeTag(SeeTag seeTag, TagletContext context, boolean plainFont)
{
StringBuffer result = new StringBuffer();
String href = null;
String label = null;
MemberDoc referencedMember = seeTag.referencedMember();
if (null != seeTag.referencedClass()) {
href = getClassDocURL(((HtmlTagletContext)context).getOutput(), seeTag.referencedClass());
Doc doc = context.getDoc();
ClassDoc classDoc = null;
if (doc.isClass() || doc.isInterface()) {
classDoc = (ClassDoc)doc;
}
else if (doc.isField() || doc.isMethod() || doc.isConstructor()) {
classDoc = ((MemberDoc)doc).containingClass();
}
if (null == referencedMember
|| seeTag.referencedClass() != classDoc
|| ((HtmlTagletContext)context).isOnSerializedPage()) {
if (!seeTag.referencedClass().isIncluded()) {
label = possiblyQualifiedName(seeTag.referencedClass());
}
else {
label = seeTag.referencedClass().typeName();
}
if (null != referencedMember) {
label += '.';
}
}
else {
label = "";
}
if (null != referencedMember) {
label += referencedMember.name();
if (referencedMember.isMethod() || referencedMember.isConstructor()) {
label += ((ExecutableMemberDoc)referencedMember).flatSignature();
}
href += '#' + getMemberAnchor(referencedMember);
}
else if (null != seeTag.referencedMemberName()) {
href = null;
}
}
else {
String referencedClassName = seeTag.referencedClassName();
if (null != referencedClassName) {
String referencedPackageName = null;
Iterator it = packageNameToDocSet.keySet().iterator();
while (it.hasNext()) {
String packageName = (String)it.next();
if ((null == referencedPackageName
|| packageName.length() > referencedPackageName.length())
&& referencedClassName.startsWith(packageName + '.')) {
referencedPackageName = packageName;
}
}
if (null != referencedPackageName) {
ExternalDocSet externalDocSet
= (ExternalDocSet)packageNameToDocSet.get(referencedPackageName);
String className = referencedClassName.substring(referencedPackageName.length() + 1);
href = externalDocSet.getClassDocURL(referencedPackageName,
className);
label = className;
String referencedMemberName = seeTag.referencedMemberName();
if (null != referencedMemberName) {
label += '.';
label += referencedMemberName;
href += '#' + transformReferencedMemberName(referencedMemberName,
externalDocSet.isJavadocCompatible());
}
else if (null != seeTag.referencedMemberName()) {
href = null;
}
}
}
}
if (null != seeTag.label()
&& seeTag.label().length() > 0) {
label = seeTag.label();
}
if (null == label) {
label = seeTag.text();
if (label.startsWith("#")) {
label = label.substring(1);
}
else {
label = label.replace('#', '.');
}
label.trim();
}
if (null != href) {
result.append("<a href=\"");
result.append(href);
result.append("\">");
if (!plainFont) {
result.append("<code>");
}
result.append(label);
if (!plainFont) {
result.append("</code>");
}
result.append("</a>");
}
else {
if (!plainFont) {
result.append("<code>");
}
result.append(label);
if (!plainFont) {
result.append("</code>");
}
}
return result.toString();
}
protected String renderTag(String tagName, Tag[] tags, TagletContext context)
{
Doc doc = context.getDoc();
if ("see".equals(tagName)
&& ((tags.length > 0)
|| (doc.isClass()
&& (((ClassDoc)doc).isSerializable()
|| ((ClassDoc)doc).isExternalizable())))) {
StringBuffer result = new StringBuffer();
result.append("<dl class=\"tag list\">");
result.append("<dt class=\"tag section header\"><b>");
result.append("See Also:");
result.append("</b></dt>");
boolean oneLine = true;
if (oneLine) {
result.append("<dd>");
}
for (int i = 0; i < tags.length; ++i) {
if (oneLine) {
if (i > 0) {
result.append(", ");
}
}
else {
result.append("<dd>");
}
result.append(renderSeeTag((SeeTag)tags[i], context, false));
if (!oneLine) {
result.append("</dd>");
}
}
if ((doc instanceof ClassDoc)
&& (((ClassDoc)doc).isSerializable() || ((ClassDoc)doc).isExternalizable())) {
if (tags.length > 0) {
result.append(", ");
}
HtmlPage output = ((HtmlTagletContext)context).getOutput();
result.append("<a href=\"" + output.getPathToRoot() + "/serialized-form" + filenameExtension + "#" + ((ClassDoc)doc).qualifiedName() + "\">Serialized Form</a>");
}
if (oneLine) {
result.append("</dd>");
}
result.append("</dl>");
return result.toString();
}
else if (tags.length > 0
&& "serial".equals(tagName)
&& ((HtmlTagletContext)context).isOnSerializedPage()) {
return renderInlineTags(tags[0].inlineTags(), context);
}
else {
return "";
}
}
private String getWindowTitle()
{
if (null == optionWindowTitle.getValue()) {
return "Generated API Documentation";
}
else {
return optionWindowTitle.getValue();
}
}
private String getPageTitle(String title)
{
if (null == optionWindowTitle.getValue()) {
return title;
}
else {
return title + " (" + optionWindowTitle.getValue() + ")";
}
}
protected String getDocletVersion()
{
if (null == docletVersion) {
try {
Properties versionProperties = new Properties();
InputStream in = getClass().getResourceAsStream("/version.properties");
if (in == null) {
in = new FileInputStream("src/resources/version.properties");
}
versionProperties.load(in);
docletVersion = versionProperties.getProperty("gjdoc.version");
}
catch (IOException ignore) {
}
if (null == docletVersion) {
docletVersion = "unknown";
}
}
return docletVersion;
}
private Map getStylesheets()
{
Map sheets = new HashMap();
if (null != optionStylesheetFile.getValue()) {
sheets.put("User-specified", new String[] {
"resources/user.css"
});
}
else {
List cleanSheets = new LinkedList();
cleanSheets.add("resources/gjdochtml-clean-layout.css");
cleanSheets.add("resources/gjdochtml-clean-color1.css");
if (null != optionAddStylesheet.getValue()) {
cleanSheets.add("resources/user.css");
}
sheets.put("GNU Clean", cleanSheets.toArray(new String[0]));
}
return sheets;
}
protected boolean isSinglePackage()
{
if (getRootDoc().firstSentenceTags().length > 0) {
return false;
}
else if (null != optionDocTitle.getValue()
|| null != optionTitle.getValue()) {
return false;
}
else {
return super.isSinglePackage();
}
}
private String getTypeParameters(ClassDoc classDoc)
{
String parameters = "";
TypeVariable[] params = classDoc.typeParameters();
if (params != null && params.length > 0)
{
parameters = "&lt;";
for (int a = 0; a < params.length; ++a)
{
parameters += params[a].typeName();
Type[] bounds = params[a].bounds();
if (bounds != null)
{
parameters += " extends ";
for (int b = 0; a < bounds.length; ++b)
{
parameters += bounds[a];
if (b != bounds.length - 1)
parameters += " & ";
}
}
if (a != params.length - 1)
parameters += ",";
}
parameters += "&gt;";
}
return parameters;
}
private String transformReferencedMemberName(String referencedMemberName,
boolean javadocCompatibility)
{
if (!javadocCompatibility) {
StringBuffer result = new StringBuffer();
for (int i=0; i<referencedMemberName.length(); ++i) {
char c = referencedMemberName.charAt(i);
switch (c) {
case '(': result.append(':'); break;
case ')': break;
case ',': result.append(':'); break;
case '[': result.append('-'); break;
case ']': break;
default: result.append(c); break;
}
}
return result.toString();
}
else {
return referencedMemberName;
}
}
public void writeGjdocProperties(File outputFile)
throws IOException
{
Properties properties = new Properties();
properties.setProperty("gjdoc.version", getDocletVersion());
properties.setProperty("gjdoc.compat", Boolean.toString(isJavadocCompatibleNames()));
FileOutputStream out = new FileOutputStream(outputFile);
properties.store(out, "GNU Gjdoc API Documentation Set Descriptor");
out.close();
}
public boolean isJavadocCompatibleNames()
{
return !optionValidHtml.getValue();
}
private HtmlPage newHtmlPage(File file,
String pathToRoot)
throws IOException
{
return new HtmlPage(file,
pathToRoot,
getOutputDocEncoding(),
optionBaseUrl.getValue(),
getTargetDirectory());
}
private HtmlPage newHtmlPage(File file,
String pathToRoot,
String docType)
throws IOException
{
return new HtmlPage(file,
pathToRoot,
getOutputDocEncoding(),
optionBaseUrl.getValue(),
getTargetDirectory(),
docType);
}
}