/* 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("<Unnamed>"); } 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("<unnamed package>"); } 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("<Unnamed>"); } 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(" "); 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 = "<"; 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 += ">"; } 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); } }