1 /* gnu.classpath.tools.doclets.htmldoclet.HtmlDoclet
2 Copyright (C) 2004, 2012 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package gnu.classpath.tools.doclets.htmldoclet;
40 import gnu.classpath.tools.IOToolkit;
42 import gnu.classpath.tools.doclets.AbstractDoclet;
43 import gnu.classpath.tools.doclets.DocletConfigurationException;
44 import gnu.classpath.tools.doclets.DocletOption;
45 import gnu.classpath.tools.doclets.DocletOptionFile;
46 import gnu.classpath.tools.doclets.DocletOptionFlag;
47 import gnu.classpath.tools.doclets.DocletOptionString;
48 import gnu.classpath.tools.doclets.PackageGroup;
49 import gnu.classpath.tools.doclets.TagletPrinter;
50 import gnu.classpath.tools.doclets.InlineTagRenderer;
52 import gnu.classpath.tools.doclets.xmldoclet.HtmlRepairer;
54 import gnu.classpath.tools.taglets.GnuExtendedTaglet;
55 import gnu.classpath.tools.taglets.TagletContext;
57 import gnu.classpath.tools.java2xhtml.Java2xhtml;
59 import gnu.classpath.tools.StringToolkit;
61 import com.sun.javadoc.*;
62 import com.sun.tools.doclets.Taglet;
64 import java.io.ByteArrayInputStream;
66 import java.io.FileInputStream;
67 import java.io.FileNotFoundException;
68 import java.io.FileOutputStream;
69 import java.io.FileReader;
70 import java.io.FileWriter;
71 import java.io.InputStream;
72 import java.io.InputStreamReader;
73 import java.io.IOException;
74 import java.io.OutputStreamWriter;
75 import java.io.PrintWriter;
76 import java.io.StringWriter;
78 import java.net.MalformedURLException;
80 import java.nio.charset.Charset;
82 import java.text.DateFormat;
83 import java.text.MessageFormat;
85 import java.util.Arrays;
86 import java.util.Calendar;
87 import java.util.Collection;
88 import java.util.Date;
89 import java.util.HashMap;
90 import java.util.Iterator;
91 import java.util.LinkedHashSet;
92 import java.util.LinkedList;
93 import java.util.List;
94 import java.util.ListIterator;
95 import java.util.Locale;
97 import java.util.Properties;
99 import java.util.SortedSet;
100 import java.util.TimeZone;
101 import java.util.TreeSet;
103 public class HtmlDoclet
104 extends AbstractDoclet
105 implements InlineTagRenderer
107 private static String filenameExtension = ".html";
110 * Contains ExternalDocSet.
112 private List<ExternalDocSet> externalDocSets = new LinkedList<ExternalDocSet>();
115 * Contains String->ExternalDocSet.
117 private Map<String,ExternalDocSet> packageNameToDocSet = new HashMap<String, ExternalDocSet>();
120 * Cache for version string from resource /version.properties
122 private String docletVersion;
125 * For now, do not output a help page.
127 private static final boolean outputHelpPage = false;
130 * Stores the output encoding (either the one specified using
131 * -charset, or the platform default encoding).
133 private String outputCharset;
135 private void printNavBar(HtmlPage output, String currentPage, ClassDoc currentClass)
137 output.beginDiv(CssClass.NAVBAR_TOP);
139 boolean overviewLevel
140 = ("overview".equals(currentPage)
141 || "full-tree".equals(currentPage)
142 || "index".equals(currentPage)
143 || "split-index".equals(currentPage)
144 || "serialized".equals(currentPage)
145 || "deprecated".equals(currentPage)
146 || "about".equals(currentPage)
149 if (!isSinglePackage()) {
150 if ("overview".equals(currentPage)) {
151 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
152 output.print("Overview");
153 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
156 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
157 output.beginAnchor(output.getPathToRoot() + "/overview-summary" + filenameExtension);
158 output.print("Overview");
160 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
166 if (!overviewLevel || isSinglePackage()) {
167 if ("package".equals(currentPage)) {
168 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
169 output.print("Package");
170 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
173 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
175 if (isSinglePackage()) {
176 packageHref = output.getPathToRoot() + "/" + getPackageURL(getSinglePackage()) + "package-summary" + filenameExtension;
179 packageHref = "package-summary" + filenameExtension;
181 output.beginAnchor(packageHref);
182 output.print("Package");
184 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
188 output.beginSpan(CssClass.NAVBAR_ITEM_DISABLED);
189 output.print("Package");
190 output.endSpan(CssClass.NAVBAR_ITEM_DISABLED);
193 if (optionUse.getValue() || optionLinkSource.getValue()) {
196 if (null != currentClass) {
197 if ("class".equals(currentPage)) {
198 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
199 output.print("Class");
200 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
203 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
204 output.beginAnchor(currentClass.name() + filenameExtension);
205 output.print("Class");
207 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
211 output.beginSpan(CssClass.NAVBAR_ITEM_DISABLED);
212 output.print("Class");
213 output.endSpan(CssClass.NAVBAR_ITEM_DISABLED);
216 if (optionUse.getValue()) {
219 if (null != currentClass) {
220 if ("uses".equals(currentPage)) {
221 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
223 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
226 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
227 output.beginAnchor(currentClass.name() + "-uses" + filenameExtension);
230 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
234 output.beginSpan(CssClass.NAVBAR_ITEM_DISABLED);
236 output.endSpan(CssClass.NAVBAR_ITEM_DISABLED);
240 if (optionLinkSource.getValue()) {
244 if ("source".equals(currentPage)) {
245 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
246 output.print("Source");
247 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
251 if (null != currentClass) {
253 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
254 String targetClassName = currentClass.name();
255 String targetAnchor = "";
256 if (null != currentClass.containingClass()) {
257 targetClassName = getOuterClassDoc(currentClass).name();
258 targetAnchor = "#line." + currentClass.position().line();
260 output.beginAnchor(targetClassName + "-source" + filenameExtension + targetAnchor);
261 output.print("Source");
263 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
266 output.beginSpan(CssClass.NAVBAR_ITEM_DISABLED);
267 output.print("Source");
268 output.endSpan(CssClass.NAVBAR_ITEM_DISABLED);
275 if (!optionNoTree.getValue()) {
278 if ("full-tree".equals(currentPage)
279 || "package-tree".equals(currentPage)) {
280 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
281 output.print("Tree");
282 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
285 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
287 if (isSinglePackage() && overviewLevel) {
288 treeHref = getPackageURL(getSinglePackage()) + "tree" + filenameExtension;
291 treeHref = "tree" + filenameExtension;
294 output.beginAnchor(treeHref);
295 output.print("Tree");
297 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
304 if (optionSplitIndex.getValue()) {
305 indexName = "alphaindex-1";
308 indexName = "alphaindex";
311 if ("index".equals(currentPage) || "split-index".equals(currentPage)) {
312 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
313 output.print("Index");
314 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
317 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
318 output.beginAnchor(output.getPathToRoot() + "/" + indexName + filenameExtension);
319 output.print("Index");
321 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
324 if (!optionNoDeprecatedList.getValue()) {
327 if ("deprecated".equals(currentPage)) {
328 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
329 output.print("Deprecated");
330 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
333 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
334 output.beginAnchor(output.getPathToRoot() + "/deprecated" + filenameExtension);
335 output.print("Deprecated");
337 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
341 if (outputHelpPage) {
342 if (!optionNoHelp.getValue()) {
345 if ("help".equals(currentPage)) {
346 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
347 output.print("Help");
348 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
351 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
352 output.beginAnchor(output.getPathToRoot() + "/help" + filenameExtension);
353 output.print("Help");
355 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
362 if ("about".equals(currentPage)) {
363 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
364 output.print("About");
365 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
368 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
369 output.beginAnchor(output.getPathToRoot() + "/about" + filenameExtension);
370 output.print("About");
372 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
375 output.endDiv(CssClass.NAVBAR_TOP);
378 private void printNavBarTopRow(HtmlPage output, String currentPage, ClassDoc currentClass)
381 output.beginCell(CssClass.NAVBAR_TOP);
382 printNavBar(output, currentPage, currentClass);
384 if (null != optionHeader.getValue()) {
385 output.beginCell(CssClass.NAVBAR_TOP_HEADER);
386 output.print(replaceDocRoot(output, optionHeader.getValue()));
392 private void printNavBarTopNaviCell(HtmlPage output)
394 output.beginCell(CssClass.NAVBAR_TOP_NAVI);
395 output.beginAnchor(output.getPathToRoot() + "/index" + filenameExtension, "Show in a frameset", "_top");
396 output.print("Frames");
400 output.beginAnchor(output.getFile().getName(), "Show without frames", "_top");
401 output.print("No Frames");
408 private void printNavBarTop(HtmlPage output, String currentPage)
410 printNavBarTop(output, currentPage, null, null, null);
413 private void printNavBarTop(HtmlPage output, String currentPage,
414 ClassDoc currentClass, Object prev, Object next)
416 if (!optionNoNavBar.getValue()) {
417 output.beginTable(CssClass.NAVBAR_TOP);
418 printNavBarTopRow(output, currentPage, currentClass);
420 if ("class".equals(currentPage)) {
421 output.beginCell(CssClass.NAVBAR_TOP_NAVI);
422 ClassDoc prevClass = (ClassDoc)prev;
423 ClassDoc nextClass = (ClassDoc)next;
424 if (null != prevClass) {
425 output.anchor(getClassDocURL(output, prevClass), "Prev Class");
428 output.print("Prev Class");
431 if (null != nextClass) {
432 output.anchor(getClassDocURL(output, nextClass), "Next Class");
435 output.print("Next Class");
439 else if ("split-index".equals(currentPage)) {
440 output.beginCell(CssClass.NAVBAR_TOP_NAVI);
441 Integer prevLetter = (Integer)prev;
442 Integer nextLetter = (Integer)next;
443 if (null != prevLetter) {
444 output.anchor("alphaindex-" + prevLetter + filenameExtension, "Prev Letter");
447 output.print("Prev Letter");
450 if (null != nextLetter) {
451 output.anchor("alphaindex-" + nextLetter + filenameExtension, "Next Letter");
454 output.print("Next Letter");
459 output.beginCell(CssClass.NAVBAR_TOP_NAVI);
463 printNavBarTopNaviCell(output);
466 if ("class".equals(currentPage)) {
469 output.beginCell(CssClass.NAVBAR_TOP_NAVI);
470 output.print("Summary: ");
472 if (currentClass.innerClasses().length > 0) {
473 output.anchor("#summary-inner", "Nested");
476 output.print("Nested");
481 if (currentClass.fields().length > 0) {
482 output.anchor("#summary-fields", "Field");
485 output.print("Field");
490 if (currentClass.methods().length > 0) {
491 output.anchor("#summary-methods", "Method");
494 output.print("Method");
499 if (currentClass.constructors().length > 0) {
500 output.anchor("#summary-constructors", "Constr");
503 output.print("Constr");
508 output.beginCell(CssClass.NAVBAR_TOP_NAVI);
509 output.print("Detail: ");
511 if (currentClass.innerClasses().length > 0) {
512 output.anchor("#detail-inner", "Nested");
515 output.print("Nested");
520 if (currentClass.fields().length > 0) {
521 output.anchor("#detail-fields", "Field");
524 output.print("Field");
529 if (currentClass.methods().length > 0) {
530 output.anchor("#detail-methods", "Method");
533 output.print("Method");
538 if (currentClass.constructors().length > 0) {
539 output.anchor("#detail-constructors", "Constr");
542 output.print("Constr");
552 private void printNavBarTopPackage(HtmlPage output, String currentPage,
553 PackageDoc prevPackage, PackageDoc nextPackage)
555 if (!optionNoNavBar.getValue()) {
556 output.beginTable(CssClass.NAVBAR_TOP);
557 printNavBarTopRow(output, currentPage, null);
560 output.beginCell(CssClass.NAVBAR_TOP_NAVI);
561 if (null != prevPackage) {
562 output.anchor(output.getPathToRoot() + "/" + getPackageURL(prevPackage) + "package-summary" + filenameExtension, "Prev Package");
565 output.print("Prev Package");
568 if (null != nextPackage) {
569 output.anchor(output.getPathToRoot() + "/" + getPackageURL(nextPackage) + "package-summary" + filenameExtension, "Next Package");
572 output.print("Next Package");
576 printNavBarTopNaviCell(output);
583 private void printNavBarBottom(HtmlPage output, String currentPage)
585 printNavBarBottom(output, currentPage, null);
588 private void printNavBarBottom(HtmlPage output, String currentPage, ClassDoc currentClass)
590 if ("class".equals(currentPage)) {
591 String boilerplate = null;
592 Tag[] boilerplateTags = getOuterClassDoc(currentClass).tags("@boilerplate");
593 if (boilerplateTags.length > 0) {
594 boilerplate = boilerplateTags[0].text();
596 if (null != boilerplate) {
598 output.beginDiv(CssClass.CLASS_BOILERPLATE);
599 output.print(boilerplate);
600 output.endDiv(CssClass.CLASS_BOILERPLATE);
605 if (!optionNoNavBar.getValue()) {
606 output.beginDiv(CssClass.NAVBAR_BOTTOM_SPACER);
608 output.endDiv(CssClass.NAVBAR_BOTTOM_SPACER);
609 output.beginTable(CssClass.NAVBAR_BOTTOM);
612 printNavBar(output, currentPage, currentClass);
614 if (null != optionFooter.getValue()) {
616 output.print(replaceDocRoot(output, optionFooter.getValue()));
623 if (null != optionBottom.getValue()) {
625 output.print(replaceDocRoot(output, optionBottom.getValue()));
629 private void printPackagePageClasses(HtmlPage output, ClassDoc[] classDocs, String header)
631 if (classDocs.length > 0) {
632 output.beginDiv(CssClass.TABLE_CONTAINER);
633 output.beginTable(CssClass.PACKAGE_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
634 output.rowDiv(CssClass.TABLE_HEADER, header);
636 for (int i=0; i<classDocs.length; ++i) {
637 ClassDoc classDoc = classDocs[i];
638 if (classDoc.isIncluded()) {
641 output.beginCell(CssClass.PACKAGE_SUMMARY_LEFT);
642 printType(output, classDoc);
645 output.beginCell(CssClass.PACKAGE_SUMMARY_RIGHT);
646 printTags(output, classDoc, classDoc.firstSentenceTags(), true);
652 output.endDiv(CssClass.TABLE_CONTAINER);
657 private void printPackagesListFile()
661 = new PrintWriter(new OutputStreamWriter(new FileOutputStream(new File(getTargetDirectory(),
665 PackageDoc[] packages = getRootDoc().specifiedPackages();
666 for (int i=0; i<packages.length; ++i) {
667 String packageName = packages[i].name();
668 if (packageName.length() > 0) {
669 out.println(packageName);
676 private void printPackagePage(File packageDir, String pathToRoot,
677 PackageDoc packageDoc,
678 PackageDoc prevPackageDoc,
679 PackageDoc nextPackageDoc)
682 HtmlPage output = newHtmlPage(new File(packageDir, "package-summary" + filenameExtension),
685 Set<String> keywords = new LinkedHashSet<String>();
686 keywords.add(packageDoc.name() + " packages");
688 output.beginPage(getPageTitle(packageDoc.name()), getOutputCharset(),
689 keywords, getStylesheets());
690 output.beginBody(CssClass.BODY_CONTENT_PACKAGE);
691 printNavBarTopPackage(output, "package", prevPackageDoc, nextPackageDoc);
693 output.beginDiv(CssClass.PACKAGE_TITLE);
694 output.print("Package ");
695 if (packageDoc.name().length() > 0) {
696 output.print(packageDoc.name());
699 output.print("<Unnamed>");
701 output.endDiv(CssClass.PACKAGE_TITLE);
703 output.beginDiv(CssClass.PACKAGE_DESCRIPTION_TOP);
704 printTags(output, packageDoc, packageDoc.firstSentenceTags(), true);
705 output.endDiv(CssClass.PACKAGE_DESCRIPTION_TOP);
707 printPackagePageClasses(output, packageDoc.interfaces(),
708 "Interface Summary");
709 printPackagePageClasses(output, packageDoc.ordinaryClasses(),
711 printPackagePageClasses(output, packageDoc.exceptions(),
712 "Exception Summary");
713 printPackagePageClasses(output, packageDoc.errors(),
716 output.anchorName("description");
717 output.beginDiv(CssClass.PACKAGE_DESCRIPTION_FULL);
718 printTags(output, packageDoc, packageDoc.inlineTags(), false);
719 output.endDiv(CssClass.PACKAGE_DESCRIPTION_FULL);
721 printNavBarBottom(output, "package");
727 static class TreeNode
728 implements Comparable<TreeNode>
731 SortedSet<TreeNode> children = new TreeSet<TreeNode>();
733 TreeNode(ClassDoc classDoc) {
734 TreeNode.this.classDoc = classDoc;
737 public boolean equals(Object other)
739 return classDoc.equals(((TreeNode)other).classDoc);
742 public int compareTo(TreeNode other)
744 return classDoc.compareTo(other.classDoc);
747 public int hashCode()
749 return classDoc.hashCode();
753 private TreeNode addClassTreeNode(Map<String,TreeNode> treeMap, ClassDoc classDoc)
755 TreeNode node = treeMap.get(classDoc.qualifiedName());
757 node = new TreeNode(classDoc);
758 treeMap.put(classDoc.qualifiedName(), node);
760 ClassDoc superClassDoc = (ClassDoc)classDoc.superclass();
761 if (null != superClassDoc) {
762 TreeNode parentNode = addClassTreeNode(treeMap, superClassDoc);
763 parentNode.children.add(node);
769 private TreeNode addInterfaceTreeNode(Map<String,TreeNode> treeMap, ClassDoc classDoc)
771 TreeNode node = treeMap.get(classDoc.qualifiedName());
773 node = new TreeNode(classDoc);
774 treeMap.put(classDoc.qualifiedName(), node);
776 ClassDoc[] superInterfaces = classDoc.interfaces();
777 if (null != superInterfaces && superInterfaces.length > 0) {
778 for (int i=0; i<superInterfaces.length; ++i) {
779 TreeNode parentNode = addInterfaceTreeNode(treeMap, superInterfaces[i]);
780 parentNode.children.add(node);
784 TreeNode rootNode = treeMap.get("<root>");
785 if (null == rootNode) {
786 rootNode = new TreeNode(null);
787 treeMap.put("<root>", rootNode);
789 rootNode.children.add(node);
795 private void printPackageTreeRec(HtmlPage output, TreeNode node, TreeNode parentNode)
797 output.beginElement("li", "class", "node");
798 output.beginElement("div");
799 if (node.classDoc.isIncluded()) {
800 String packageName = node.classDoc.containingPackage().name();
801 if (packageName.length() > 0) {
802 output.print(packageName);
805 output.beginSpan(CssClass.TREE_LINK);
806 printType(output, node.classDoc);
807 output.endSpan(CssClass.TREE_LINK);
810 output.print(possiblyQualifiedName(node.classDoc));
812 ClassDoc[] interfaces = node.classDoc.interfaces();
813 ClassDoc parentClassDoc = null;
814 if (null != parentNode) {
815 parentClassDoc = parentNode.classDoc;
817 if (interfaces.length > 0
818 && !(interfaces.length == 1 && interfaces[0].equals(parentClassDoc))) {
819 if (node.classDoc.isInterface()) {
820 output.print(" (also implements ");
823 output.print(" (implements ");
826 boolean firstItem = true;
827 for (int i=0; i<interfaces.length; ++i) {
828 ClassDoc implemented = interfaces[i];
829 if (!implemented.equals(parentClassDoc)) {
834 if (implemented.isIncluded()) {
835 output.print(implemented.containingPackage().name());
837 printType(output, implemented);
840 output.print(possiblyQualifiedName(implemented));
847 output.endElement("div");
848 output.endElement("li");
849 if (!node.children.isEmpty()) {
850 output.beginElement("li", "class", "level");
851 output.beginElement("ul");
852 Iterator<TreeNode> it = node.children.iterator();
853 while (it.hasNext()) {
854 printPackageTreeRec(output, it.next(), node);
856 output.endElement("ul");
857 output.endElement("li");
861 private void printClassTree(HtmlPage output, ClassDoc[] classDocs)
863 Map<String,TreeNode> classTreeMap = new HashMap<String,TreeNode>();
865 for (int i=0; i<classDocs.length; ++i) {
866 ClassDoc classDoc = classDocs[i];
867 if (!classDoc.isInterface()) {
868 addClassTreeNode(classTreeMap, classDoc);
872 TreeNode root = classTreeMap.get("java.lang.Object");
874 output.div(CssClass.PACKAGE_TREE_SECTION_TITLE, "Class Hierarchy");
875 output.beginDiv(CssClass.PACKAGE_TREE);
876 printPackageTreeRec(output, root, null);
877 output.endDiv(CssClass.PACKAGE_TREE);
881 private void printInterfaceTree(HtmlPage output, ClassDoc[] classDocs)
883 Map<String,TreeNode> interfaceTreeMap = new HashMap<String,TreeNode>();
885 for (int i=0; i<classDocs.length; ++i) {
886 ClassDoc classDoc = classDocs[i];
887 if (classDoc.isInterface()) {
888 addInterfaceTreeNode(interfaceTreeMap, classDoc);
892 TreeNode interfaceRoot = interfaceTreeMap.get("<root>");
893 if (null != interfaceRoot) {
894 Iterator<TreeNode> it = interfaceRoot.children.iterator();
896 output.div(CssClass.PACKAGE_TREE_SECTION_TITLE, "Interface Hierarchy");
897 output.beginDiv(CssClass.PACKAGE_TREE);
898 while (it.hasNext()) {
899 TreeNode node = it.next();
900 printPackageTreeRec(output, node, null);
902 output.endDiv(CssClass.PACKAGE_TREE);
908 private void printPackageTreePage(File packageDir, String pathToRoot, PackageDoc packageDoc)
911 HtmlPage output = newHtmlPage(new File(packageDir,
912 "tree" + filenameExtension),
914 output.beginPage(getPageTitle(packageDoc.name() + " Hierarchy"),
917 output.beginBody(CssClass.BODY_CONTENT_PACKAGE_TREE);
918 printNavBarTop(output, "package-tree");
920 output.div(CssClass.PACKAGE_TREE_TITLE, "Hierarchy for Package " + packageDoc.name());
922 ClassDoc[] classDocs = packageDoc.allClasses();
923 printClassTree(output, classDocs);
924 printInterfaceTree(output, classDocs);
926 printNavBarBottom(output, "package-tree");
932 private void printFullTreePage()
935 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
936 "tree" + filenameExtension),
938 output.beginPage(getPageTitle("Hierarchy"),
941 output.beginBody(CssClass.BODY_CONTENT_FULL_TREE);
942 printNavBarTop(output, "full-tree");
944 output.div(CssClass.PACKAGE_TREE_TITLE, "Hierarchy for All Packages");
946 output.beginDiv(CssClass.FULL_TREE_PACKAGELIST);
947 output.div(CssClass.FULL_TREE_PACKAGELIST_HEADER, "Package Hierarchies:");
948 output.beginDiv(CssClass.FULL_TREE_PACKAGELIST_ITEM);
949 Set<PackageDoc> allPackages = getAllPackages();
950 Iterator<PackageDoc> it = allPackages.iterator();
951 while (it.hasNext()) {
952 PackageDoc packageDoc = it.next();
953 output.beginAnchor(getPackageURL(packageDoc) + "tree" + filenameExtension);
954 output.print(packageDoc.name());
960 output.endDiv(CssClass.FULL_TREE_PACKAGELIST_ITEM);
961 output.endDiv(CssClass.FULL_TREE_PACKAGELIST);
963 ClassDoc[] classDocs = getRootDoc().classes();
964 printClassTree(output, classDocs);
965 printInterfaceTree(output, classDocs);
967 printNavBarBottom(output, "full-tree");
973 private void printIndexEntry(HtmlPage output, Doc entry)
975 output.beginDiv(CssClass.INDEX_ENTRY);
976 output.beginDiv(CssClass.INDEX_ENTRY_KEY);
977 if (entry instanceof PackageDoc) {
978 output.beginAnchor(getPackageURL((PackageDoc)entry) + "package-summary" + filenameExtension);
979 output.print(entry.name());
981 output.print(" - package");
983 else if (entry instanceof ClassDoc) {
984 ClassDoc classDoc = (ClassDoc)entry;
985 output.beginAnchor(getClassURL(classDoc));
986 output.print(entry.name() + getTypeParameters(classDoc));
989 if (entry.isInterface()) {
990 output.print("interface ");
992 else if (entry.isException()) {
993 output.print("exception ");
995 else if (entry.isError()) {
996 output.print("error ");
999 output.print("class ");
1001 String packageName = classDoc.containingPackage().name();
1002 if (packageName.length() > 0) {
1003 output.print(packageName);
1006 printType(output, classDoc);
1009 ProgramElementDoc memberDoc = (ProgramElementDoc)entry;
1010 output.beginAnchor(getMemberDocURL(output, memberDoc));
1011 output.print(entry.name());
1012 if (memberDoc instanceof ExecutableMemberDoc) {
1013 output.print(((ExecutableMemberDoc)memberDoc).signature());
1016 output.print(" - ");
1018 if (memberDoc.isStatic()) {
1019 output.print("static ");
1022 if (entry.isConstructor()) {
1023 output.print("constructor for class ");
1025 else if (entry.isMethod()) {
1026 output.print("method in class ");
1028 else if (entry.isField()) {
1029 output.print("field in class ");
1031 ClassDoc containingClass = memberDoc.containingClass();
1032 String packageName = containingClass.containingPackage().name();
1033 if (packageName.length() > 0) {
1034 output.print(packageName);
1037 printType(output, containingClass);
1039 output.endDiv(CssClass.INDEX_ENTRY_KEY);
1040 output.beginDiv(CssClass.INDEX_ENTRY_DESCRIPTION);
1041 printTags(output, entry, entry.firstSentenceTags(), true);
1042 output.endDiv(CssClass.INDEX_ENTRY_DESCRIPTION);
1043 output.endDiv(CssClass.INDEX_ENTRY);
1046 private void printFrameSetPage()
1049 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1050 "index" + filenameExtension),
1052 HtmlPage.DOCTYPE_FRAMESET);
1054 String title = getWindowTitle();
1055 output.beginPage(title, getOutputCharset(), getStylesheets());
1056 output.beginElement("frameset", "cols", "20%,80%");
1059 if (isSinglePackage()) {
1060 output.atomicElement("frame",
1061 new String[] { "src", "name" },
1062 new String[] { getPackageURL(getSinglePackage()) + "classes" + filenameExtension, "classes" });
1063 contentURL = getPackageURL(getSinglePackage()) + "package-summary.html";
1066 output.beginElement("frameset", "rows", "25%,75%");
1067 output.atomicElement("frame",
1068 new String[] { "src", "name" },
1069 new String[] { "all-packages" + filenameExtension, "packages" });
1070 output.atomicElement("frame",
1071 new String[] { "src", "name" },
1072 new String[] { "all-classes" + filenameExtension, "classes" });
1073 output.endElement("frameset");
1074 contentURL = "overview-summary" + filenameExtension;
1076 output.atomicElement("frame",
1077 new String[] { "src", "name" },
1078 new String[] { contentURL, "content" });
1079 output.endElement("frameset");
1084 private void printPackagesMenuPage()
1087 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1088 "all-packages" + filenameExtension),
1090 output.beginPage(getPageTitle("Package Menu"), getOutputCharset(), getStylesheets());
1091 output.beginBody(CssClass.BODY_MENU_PACKAGES, false);
1093 output.beginSpan(CssClass.PACKAGE_MENU_ENTRY);
1094 output.beginAnchor("all-classes" + filenameExtension,
1097 output.print("All Classes");
1099 output.endSpan(CssClass.PACKAGE_MENU_ENTRY);
1101 output.div(CssClass.PACKAGE_MENU_TITLE, "Packages");
1103 output.beginDiv(CssClass.PACKAGE_MENU_LIST);
1105 Set<PackageDoc> packageDocs = getAllPackages();
1106 Iterator<PackageDoc> it = packageDocs.iterator();
1107 while (it.hasNext()) {
1108 PackageDoc packageDoc = it.next();
1109 output.beginSpan(CssClass.PACKAGE_MENU_ENTRY);
1110 output.beginAnchor(getPackageURL(packageDoc) + "classes" + filenameExtension,
1113 if (packageDoc.name().length() > 0) {
1114 output.print(packageDoc.name());
1117 output.print("<unnamed package>");
1120 output.endSpan(CssClass.PACKAGE_MENU_ENTRY);
1124 output.endDiv(CssClass.PACKAGE_MENU_LIST);
1130 private void printClassMenuEntry(HtmlPage output, ClassDoc classDoc)
1132 CssClass entryClass;
1133 if (classDoc.isInterface()) {
1134 entryClass = CssClass.CLASS_MENU_ENTRY_INTERFACE;
1137 entryClass = CssClass.CLASS_MENU_ENTRY_CLASS;
1139 output.beginSpan(entryClass);
1140 output.beginAnchor(getClassDocURL(output, classDoc),
1141 classDoc.qualifiedTypeName(),
1143 output.print(classDoc.name());
1145 output.endSpan(entryClass);
1149 private void printClassMenuSection(HtmlPage output, Collection classDocs, String header)
1151 if (!classDocs.isEmpty()) {
1152 output.div(CssClass.CLASS_MENU_SUBTITLE, header);
1153 Iterator<ClassDoc> it = classDocs.iterator();
1154 while (it.hasNext()) {
1155 ClassDoc classDoc = it.next();
1156 printClassMenuEntry(output, classDoc);
1161 private void printClassMenuList(HtmlPage output, ClassDoc[] classDocs, boolean categorized)
1163 output.beginDiv(CssClass.CLASS_MENU_LIST);
1166 Set<ClassDoc> classes = new TreeSet<ClassDoc>();
1167 Set<ClassDoc> interfaces = new TreeSet<ClassDoc>();
1168 Set<ClassDoc> exceptions = new TreeSet<ClassDoc>();
1169 Set<ClassDoc> errors = new TreeSet<ClassDoc>();
1171 for (int i=0; i<classDocs.length; ++i) {
1172 ClassDoc classDoc = classDocs[i];
1173 if (classDoc.isInterface()) {
1174 interfaces.add(classDoc);
1176 else if (classDoc.isException()) {
1177 exceptions.add(classDoc);
1179 else if (classDoc.isError()) {
1180 errors.add(classDoc);
1183 classes.add(classDoc);
1186 printClassMenuSection(output, interfaces, "Interfaces");
1187 printClassMenuSection(output, classes, "Classes");
1188 printClassMenuSection(output, exceptions, "Exceptions");
1189 printClassMenuSection(output, errors, "Errors");
1192 for (int i=0; i<classDocs.length; ++i) {
1193 ClassDoc classDoc = classDocs[i];
1194 if (classDoc.isIncluded()) {
1195 printClassMenuEntry(output, classDoc);
1200 output.endDiv(CssClass.CLASS_MENU_LIST);
1203 private void printAllClassesMenuPage()
1206 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1207 "all-classes" + filenameExtension),
1209 output.beginPage(getPageTitle("Class Menu"), getOutputCharset(), getStylesheets());
1210 output.beginBody(CssClass.BODY_MENU_CLASSES, false);
1212 output.div(CssClass.CLASS_MENU_TITLE, "All Classes");
1214 printClassMenuList(output, getRootDoc().classes(), false);
1221 private void printPackageClassesMenuPage(File packageDir, String pathToRoot, PackageDoc packageDoc)
1224 HtmlPage output = newHtmlPage(new File(packageDir,
1225 "classes" + filenameExtension),
1228 output.beginPage(getPageTitle(packageDoc.name() + " Class Menu"),
1229 getOutputCharset(), getStylesheets());
1230 output.beginBody(CssClass.BODY_MENU_CLASSES, false);
1232 output.beginDiv(CssClass.CLASS_MENU_TITLE);
1233 output.beginAnchor("package-summary" + filenameExtension, "", "content");
1234 if (packageDoc.name().length() > 0) {
1235 output.print(packageDoc.name());
1238 output.print("<Unnamed>");
1241 output.endDiv(CssClass.CLASS_MENU_TITLE);
1243 printClassMenuList(output, packageDoc.allClasses(), true);
1250 private void printSplitIndex()
1253 Map<Character,List<Doc>> categorizedIndex = getCategorizedIndex();
1254 Iterator<Character> it = categorizedIndex.keySet().iterator();
1256 int count = categorizedIndex.size();
1257 while (it.hasNext()) {
1258 Character c = it.next();
1259 List<Doc> classList = categorizedIndex.get(c);
1260 printIndexPage(n++, count, c, classList);
1264 private void printIndexPage()
1267 printIndexPage(0, 0, null, null);
1270 private void printIndexPage(int index, int maxIndex, Character letter, List<Doc> classList)
1273 String pageName = "alphaindex";
1274 if (null != letter) {
1275 pageName += "-" + index;
1277 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1278 pageName + filenameExtension),
1280 output.beginPage(getPageTitle("Alphabetical Index"),
1283 output.beginBody(CssClass.BODY_CONTENT_INDEX);
1284 if (null == letter) {
1285 printNavBarTop(output, "index");
1288 printNavBarTop(output, "split-index", null,
1289 (index > 1) ? new Integer(index - 1) : null,
1290 (index < maxIndex) ? new Integer(index + 1) : null);
1295 if (null == letter) {
1296 title = "Alphabetical Index";
1299 title = "Alphabetical Index: " + letter;
1301 output.div(CssClass.INDEX_TITLE, title);
1303 if (null != letter || getCategorizedIndex().keySet().size() > 1) {
1304 output.beginDiv(CssClass.INDEX_LETTERS);
1306 Iterator it = getCategorizedIndex().keySet().iterator();
1308 while (it.hasNext()) {
1309 Character c = (Character)it.next();
1310 output.beginSpan(CssClass.INDEX_LETTER);
1311 if (letter != null) {
1312 output.beginAnchor("alphaindex-" + n + filenameExtension);
1315 output.beginAnchor("#" + c);
1317 output.print(c.toString());
1319 output.endSpan(CssClass.INDEX_LETTER);
1320 output.beginSpan(CssClass.INDEX_LETTER_SPACER);
1322 output.endSpan(CssClass.INDEX_LETTER_SPACER);
1327 output.endDiv(CssClass.INDEX_LETTERS);
1330 if (null != letter) {
1331 printIndexCategory(output, letter, classList);
1334 Map<Character,List<Doc>> categorizedIndex = getCategorizedIndex();
1335 Iterator<Character> categoryIt = categorizedIndex.keySet().iterator();
1337 while (categoryIt.hasNext()) {
1338 letter = categoryIt.next();
1339 classList = categorizedIndex.get(letter);
1340 output.anchorName(letter.toString());
1341 printIndexCategory(output, letter, classList);
1345 printNavBarBottom(output, "index");
1351 private void printIndexCategory(HtmlPage output, Character letter, List classList)
1353 Iterator it = classList.iterator();
1355 output.div(CssClass.INDEX_CATEGORY_HEADER, letter.toString());
1356 output.beginDiv(CssClass.INDEX_CATEGORY);
1357 while (it.hasNext()) {
1358 Doc entry = (Doc)it.next();
1359 printIndexEntry(output, entry);
1361 output.endDiv(CssClass.INDEX_CATEGORY);
1364 private void printDeprecationSummary(HtmlPage output, List docs, String header)
1366 if (!docs.isEmpty()) {
1367 output.beginDiv(CssClass.TABLE_CONTAINER);
1368 output.beginTable(CssClass.DEPRECATION_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
1369 output.rowDiv(CssClass.TABLE_HEADER, header);
1371 Iterator it = docs.iterator();
1372 while (it.hasNext()) {
1373 Doc doc = (Doc)it.next();
1376 output.beginCell(CssClass.DEPRECATION_SUMMARY_LEFT);
1377 if (doc instanceof Type) {
1378 printType(output, (Type)doc);
1381 ProgramElementDoc memberDoc = (ProgramElementDoc)doc;
1382 output.beginAnchor(getMemberDocURL(output, memberDoc));
1383 output.print(memberDoc.containingClass().qualifiedName());
1385 output.print(memberDoc.name());
1386 if (memberDoc instanceof ExecutableMemberDoc) {
1387 output.print(((ExecutableMemberDoc)memberDoc).flatSignature());
1391 output.beginDiv(CssClass.DEPRECATION_SUMMARY_DESCRIPTION);
1392 printTags(output, doc, doc.tags("deprecated")[0].firstSentenceTags(), true);
1393 output.endDiv(CssClass.DEPRECATION_SUMMARY_DESCRIPTION);
1400 output.endDiv(CssClass.TABLE_CONTAINER);
1406 private void printSerializationPage()
1409 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1410 "serialized-form" + filenameExtension),
1412 output.beginPage(getPageTitle("Serialized Form"),
1415 output.beginBody(CssClass.BODY_CONTENT_DEPRECATED);
1416 printNavBarTop(output, "serialized");
1418 output.div(CssClass.SERIALIZED_TITLE, "Serialized Form");
1420 Iterator<PackageDoc> it = getAllPackages().iterator();
1422 while (it.hasNext()) {
1424 PackageDoc packageDoc = it.next();
1426 List<ClassDoc> serializableClasses = new LinkedList<ClassDoc>();
1427 ClassDoc[] classes = packageDoc.allClasses();
1428 for (int i=0; i<classes.length; ++i) {
1429 ClassDoc classDoc = classes[i];
1430 if (classDoc.isSerializable() || classDoc.isExternalizable()) {
1431 serializableClasses.add(classDoc);
1435 if (!serializableClasses.isEmpty()) {
1436 output.div(CssClass.SERIALIZED_PACKAGE_HEADER, "Package " + packageDoc.name());
1438 Iterator<ClassDoc> cit = serializableClasses.iterator();
1439 while (cit.hasNext()) {
1440 ClassDoc classDoc = cit.next();
1442 output.anchorName(classDoc.qualifiedTypeName());
1444 output.beginDiv(CssClass.SERIALIZED_CLASS_HEADER);
1445 output.print("Class ");
1446 printType(output, classDoc, true);
1447 output.print(" extends ");
1448 printType(output, classDoc.superclass());
1449 output.print(" implements Serializable");
1450 output.endDiv(CssClass.SERIALIZED_CLASS_HEADER);
1452 FieldDoc serialVersionUidField = findField(classDoc, "serialVersionUID");
1453 if (null != serialVersionUidField
1454 && serialVersionUidField.isFinal()
1455 && serialVersionUidField.isStatic()
1456 && serialVersionUidField.type().typeName().equals("long")) {
1458 String fieldValue = serialVersionUidField.constantValueExpression();
1459 if (null != fieldValue) {
1460 output.beginDiv(CssClass.SERIALIZED_SVUID_OUTER);
1461 output.span(CssClass.SERIALIZED_SVUID_HEADER, "serialVersionUID: ");
1462 output.span(CssClass.SERIALIZED_SVUID_VALUE, fieldValue);
1463 output.endDiv(CssClass.SERIALIZED_SVUID_OUTER);
1466 printMemberDetails(output,
1467 classDoc.serializationMethods(),
1468 "Serialization Methods",
1470 printMemberDetails(output,
1471 classDoc.serializableFields(),
1472 "Serialized Fields",
1478 printNavBarBottom(output, "serialized");
1486 private void printDeprecationPage()
1489 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1490 "deprecated" + filenameExtension),
1492 output.beginPage(getPageTitle("Deprecated API"),
1495 output.beginBody(CssClass.BODY_CONTENT_DEPRECATED);
1496 printNavBarTop(output, "deprecated");
1498 output.div(CssClass.DEPRECATION_TITLE, "Deprecated API");
1500 List<ClassDoc> deprecatedInterfaces = new LinkedList<ClassDoc>();
1501 List<ClassDoc> deprecatedExceptions = new LinkedList<ClassDoc>();
1502 List<ClassDoc> deprecatedErrors = new LinkedList<ClassDoc>();
1503 List<ClassDoc> deprecatedClasses = new LinkedList<ClassDoc>();
1504 List<FieldDoc> deprecatedFields = new LinkedList<FieldDoc>();
1505 List<MethodDoc> deprecatedMethods = new LinkedList<MethodDoc>();
1506 List<ConstructorDoc> deprecatedConstructors = new LinkedList<ConstructorDoc>();
1508 ClassDoc[] classDocs = getRootDoc().classes();
1509 for (int i=0; i<classDocs.length; ++i) {
1510 ClassDoc classDoc = classDocs[i];
1512 Tag[] deprecatedTags = classDoc.tags("deprecated");
1513 if (null != deprecatedTags && deprecatedTags.length > 0) {
1514 if (classDoc.isInterface()) {
1515 deprecatedInterfaces.add(classDoc);
1517 else if (classDoc.isException()) {
1518 deprecatedExceptions.add(classDoc);
1520 else if (classDoc.isError()) {
1521 deprecatedErrors.add(classDoc);
1524 deprecatedClasses.add(classDoc);
1528 ConstructorDoc[] constructors = classDoc.constructors();
1529 for (int j=0; j<constructors.length; ++j) {
1530 Tag[] deprecatedTags = constructors[j].tags("deprecated");
1531 if (null != deprecatedTags && deprecatedTags.length > 0) {
1532 deprecatedConstructors.add(constructors[j]);
1535 MethodDoc[] methods = classDoc.methods();
1536 for (int j=0; j<methods.length; ++j) {
1537 Tag[] deprecatedTags = methods[j].tags("deprecated");
1538 if (null != deprecatedTags && deprecatedTags.length > 0) {
1539 deprecatedMethods.add(methods[j]);
1542 FieldDoc[] fields = classDoc.fields();
1543 for (int j=0; j<fields.length; ++j) {
1544 Tag[] deprecatedTags = fields[j].tags("deprecated");
1545 if (null != deprecatedTags && deprecatedTags.length > 0) {
1546 deprecatedFields.add(fields[j]);
1551 if (!deprecatedInterfaces.isEmpty()
1552 || !deprecatedClasses.isEmpty()
1553 || !deprecatedExceptions.isEmpty()
1554 || !deprecatedErrors.isEmpty()
1555 || !deprecatedFields.isEmpty()
1556 || !deprecatedMethods.isEmpty()
1557 || !deprecatedConstructors.isEmpty()) {
1559 output.beginDiv(CssClass.DEPRECATION_TOC);
1560 output.div(CssClass.DEPRECATION_TOC_HEADER, "Contents");
1561 output.beginDiv(CssClass.DEPRECATION_TOC_LIST);
1562 if (!deprecatedInterfaces.isEmpty()) {
1563 output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
1564 output.anchor("#interfaces", "Deprecated Interfaces");
1565 output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
1567 if (!deprecatedClasses.isEmpty()) {
1568 output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
1569 output.anchor("#classes", "Deprecated Classes");
1570 output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
1572 if (!deprecatedExceptions.isEmpty()) {
1573 output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
1574 output.anchor("#exceptions", "Deprecated Exceptions");
1575 output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
1577 if (!deprecatedErrors.isEmpty()) {
1578 output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
1579 output.anchor("#errors", "Deprecated Errors");
1580 output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
1582 if (!deprecatedFields.isEmpty()) {
1583 output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
1584 output.anchor("#fields", "Deprecated Fields");
1585 output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
1587 if (!deprecatedMethods.isEmpty()) {
1588 output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
1589 output.anchor("#methods", "Deprecated Methods");
1590 output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
1592 if (!deprecatedConstructors.isEmpty()) {
1593 output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
1594 output.anchor("#constructors", "Deprecated Constructors");
1595 output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
1597 output.endDiv(CssClass.DEPRECATION_TOC_LIST);
1598 output.endDiv(CssClass.DEPRECATION_TOC);
1599 output.beginDiv(CssClass.DEPRECATION_LIST);
1601 output.anchorName("interfaces");
1602 printDeprecationSummary(output, deprecatedInterfaces, "Deprecated Interfaces");
1604 output.anchorName("classes");
1605 printDeprecationSummary(output, deprecatedClasses, "Deprecated Classes");
1607 output.anchorName("exceptions");
1608 printDeprecationSummary(output, deprecatedExceptions, "Deprecated Exceptions");
1610 output.anchorName("errors");
1611 printDeprecationSummary(output, deprecatedErrors, "Deprecated Errors");
1613 output.anchorName("fields");
1614 printDeprecationSummary(output, deprecatedFields, "Deprecated Fields");
1616 output.anchorName("methods");
1617 printDeprecationSummary(output, deprecatedMethods, "Deprecated Methods");
1619 output.anchorName("constructors");
1620 printDeprecationSummary(output, deprecatedConstructors, "Deprecated Constructors");
1622 output.endDiv(CssClass.DEPRECATION_LIST);
1625 output.beginDiv(CssClass.DEPRECATION_EMPTY);
1626 output.print("No deprecated classes or class members in this API.");
1627 output.endDiv(CssClass.DEPRECATION_EMPTY);
1631 printNavBarBottom(output, "deprecated");
1637 private void printAboutPage()
1640 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1641 "about" + filenameExtension),
1643 output.beginPage(getPageTitle("About"),
1646 output.beginBody(CssClass.BODY_CONTENT_ABOUT);
1648 printNavBarTop(output, "about");
1650 output.div(CssClass.ABOUT_TITLE, "About");
1652 output.beginDiv(CssClass.ABOUT_GENERATOR);
1653 output.print("Generated by ");
1654 output.print("Gjdoc");
1655 output.print(" HtmlDoclet ");
1656 output.print(getDocletVersion());
1657 output.print(", part of ");
1658 output.beginAnchor("http://www.gnu.org/software/classpath/cp-tools/", "", "_top");
1659 output.print("GNU Classpath Tools");
1661 output.print(", on ");
1662 DateFormat format = DateFormat.getDateTimeInstance(DateFormat.LONG,
1665 Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"),
1667 format.setCalendar(cal);
1668 output.print(format.format(new Date()));
1670 output.endDiv(CssClass.ABOUT_GENERATOR);
1672 printNavBarBottom(output, "about");
1679 private void printSourcePage(File packageDir, ClassDoc classDoc, String sourceXhtml)
1682 HtmlPage output = newHtmlPage(new File(packageDir,
1683 classDoc.name() + "-source" + filenameExtension),
1684 getPathToRoot(packageDir, getTargetDirectory()));
1685 output.beginPage(getPageTitle("Source for " + classDoc.qualifiedTypeName()),
1689 output.beginBody(CssClass.BODY_CONTENT_SOURCE);
1691 printNavBarTop(output, "source", classDoc, null, null);
1693 output.div(CssClass.SOURCE_TITLE, "Source for " + classDoc.qualifiedTypeName());
1694 output.beginDiv(CssClass.SOURCE);
1695 output.print(sourceXhtml);
1696 output.endDiv(CssClass.SOURCE);
1698 printNavBarBottom(output, "source", classDoc);
1706 private void printHelpPage()
1709 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1710 "help" + filenameExtension),
1712 output.beginPage(getPageTitle("Help"),
1715 output.beginBody(CssClass.BODY_CONTENT_HELP);
1717 printNavBarTop(output, "help");
1720 if (null != optionHelpFile.getValue()){
1721 helpIn = new FileInputStream(optionHelpFile.getValue());
1724 helpIn = getClass().getResourceAsStream("/htmldoclet/help.xhtml");
1726 output.insert(new InputStreamReader(helpIn, "utf-8"));
1729 printNavBarBottom(output, "help");
1736 private void printOverviewPage()
1739 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1740 "overview-summary" + filenameExtension),
1742 output.beginPage(getWindowTitle(),
1745 output.beginBody(CssClass.BODY_CONTENT_OVERVIEW);
1747 printNavBarTop(output, "overview");
1749 String overviewHeader;
1750 if (null != optionDocTitle.getValue()) {
1751 overviewHeader = optionDocTitle.getValue();
1753 else if (null != optionTitle.getValue()) {
1754 overviewHeader = optionTitle.getValue();
1757 overviewHeader = null;
1760 if (null != overviewHeader) {
1761 output.div(CssClass.OVERVIEW_TITLE, overviewHeader);
1764 output.beginDiv(CssClass.OVERVIEW_DESCRIPTION_TOP);
1765 printTags(output, getRootDoc(), getRootDoc().firstSentenceTags(), true);
1766 output.endDiv(CssClass.OVERVIEW_DESCRIPTION_TOP);
1768 List packageGroups = getPackageGroups();
1770 if (packageGroups.isEmpty()) {
1772 printOverviewPackages(output, getAllPackages(),
1776 Set otherPackages = new LinkedHashSet();
1777 otherPackages.addAll(getAllPackages());
1779 Iterator it = packageGroups.iterator();
1780 while (it.hasNext()) {
1781 PackageGroup packageGroup = (PackageGroup)it.next();
1782 printOverviewPackages(output,
1783 packageGroup.getPackages(),
1784 packageGroup.getName());
1785 otherPackages.removeAll(packageGroup.getPackages());
1788 if (!otherPackages.isEmpty()) {
1789 printOverviewPackages(output,
1795 output.anchorName("description");
1796 output.beginDiv(CssClass.OVERVIEW_DESCRIPTION_FULL);
1797 printTags(output, getRootDoc(), getRootDoc().inlineTags(), false);
1798 output.endDiv(CssClass.OVERVIEW_DESCRIPTION_FULL);
1800 printNavBarBottom(output, "overview");
1806 private void printOverviewPackages(HtmlPage output, Collection packageDocs, String header)
1808 output.beginDiv(CssClass.TABLE_CONTAINER);
1809 output.beginTable(CssClass.OVERVIEW_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
1810 output.rowDiv(CssClass.TABLE_HEADER, header);
1812 Iterator it = packageDocs.iterator();
1813 while (it.hasNext()) {
1814 PackageDoc packageDoc = (PackageDoc)it.next();
1817 output.beginCell(CssClass.OVERVIEW_SUMMARY_LEFT);
1818 output.beginAnchor(getPackageURL(packageDoc) + "package-summary" + filenameExtension);
1819 output.print(packageDoc.name());
1823 output.beginCell(CssClass.OVERVIEW_SUMMARY_RIGHT);
1824 printTags(output, packageDoc, packageDoc.firstSentenceTags(), true);
1829 output.endDiv(CssClass.TABLE_CONTAINER);
1832 private void printClassUsagePage(File packageDir, String pathToRoot, ClassDoc classDoc)
1835 HtmlPage output = newHtmlPage(new File(packageDir,
1836 classDoc.name() + "-uses" + filenameExtension),
1838 output.beginPage(getPageTitle(classDoc.name()), getOutputCharset(), getStylesheets());
1839 output.beginBody(CssClass.BODY_CONTENT_USES);
1840 printNavBarTop(output, "uses", classDoc, null, null);
1842 output.div(CssClass.USAGE_TITLE,
1843 "Uses of " + getClassTypeName(classDoc)
1844 + " " + classDoc.qualifiedName());
1846 Map packageToUsageTypeMap = getUsageOfClass(classDoc);
1847 if (null != packageToUsageTypeMap && !packageToUsageTypeMap.isEmpty()) {
1849 Iterator packagesIterator = packageToUsageTypeMap.keySet().iterator();
1850 while (packagesIterator.hasNext()) {
1851 PackageDoc packageDoc = (PackageDoc)packagesIterator.next();
1853 output.div(CssClass.USAGE_PACKAGE_TITLE, "Uses in package " + packageDoc.name());
1855 Map usageTypeToUsersMap = (Map)packageToUsageTypeMap.get(packageDoc);
1856 Iterator usageTypeIterator = usageTypeToUsersMap.keySet().iterator();
1857 while (usageTypeIterator.hasNext()) {
1858 UsageType usageType = (UsageType)usageTypeIterator.next();
1860 output.beginTable(CssClass.USAGE_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
1861 output.rowDiv(CssClass.USAGE_TABLE_HEADER, format("usagetype." + usageType.getId(),
1862 classDoc.qualifiedName()));
1864 Set users = (Set)usageTypeToUsersMap.get(usageType);
1865 Iterator userIterator = users.iterator();
1866 while (userIterator.hasNext()) {
1867 Doc user = (Doc)userIterator.next();
1871 if (user instanceof ClassDoc) {
1872 output.beginCell(CssClass.USAGE_SUMMARY_LEFT);
1873 output.print("class");
1876 output.beginCell(CssClass.USAGE_SUMMARY_RIGHT);
1877 output.beginDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
1878 printType(output, ((ClassDoc)user));
1879 output.endDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
1880 output.beginDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
1881 printTags(output, ((ClassDoc)user), ((ClassDoc)user).firstSentenceTags(), true);
1882 output.endDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
1885 else if (user instanceof FieldDoc) {
1886 FieldDoc fieldDoc = (FieldDoc)user;
1888 output.beginCell(CssClass.USAGE_SUMMARY_LEFT);
1889 printType(output, ((FieldDoc)user).type());
1892 output.beginCell(CssClass.USAGE_SUMMARY_RIGHT);
1893 output.beginDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
1894 printType(output, ((FieldDoc)user).containingClass());
1896 output.beginAnchor(getMemberDocURL(output, (FieldDoc)user));
1897 output.print(((FieldDoc)user).name());
1899 output.endDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
1900 output.beginDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
1901 printTags(output, ((FieldDoc)user), ((FieldDoc)user).firstSentenceTags(), true);
1902 output.endDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
1905 else if (user instanceof MethodDoc) {
1906 MethodDoc methodDoc = (MethodDoc)user;
1908 output.beginCell(CssClass.USAGE_SUMMARY_LEFT);
1909 printType(output, ((MethodDoc)user).returnType());
1912 output.beginCell(CssClass.USAGE_SUMMARY_RIGHT);
1913 output.beginDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
1914 printType(output, ((MethodDoc)user).containingClass());
1916 output.beginAnchor(getMemberDocURL(output, (MethodDoc)user));
1917 output.print(((MethodDoc)user).name());
1919 printParameters(output, (ExecutableMemberDoc)user);
1920 output.endDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
1921 output.beginDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
1922 printTags(output, ((MethodDoc)user), ((MethodDoc)user).firstSentenceTags(), true);
1923 output.endDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
1926 else if (user instanceof ConstructorDoc) {
1927 ConstructorDoc constructorDoc = (ConstructorDoc)user;
1929 output.beginCell(CssClass.USAGE_SUMMARY_RIGHT);
1930 output.beginDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
1931 printType(output, ((ConstructorDoc)user).containingClass());
1933 output.beginAnchor(getMemberDocURL(output, (ConstructorDoc)user));
1934 output.print(((ConstructorDoc)user).name());
1936 printParameters(output, (ExecutableMemberDoc)user);
1937 output.endDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
1938 output.beginDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
1939 printTags(output, ((ConstructorDoc)user),
1940 ((ConstructorDoc)user).firstSentenceTags(), true);
1941 output.endDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
1952 output.div(CssClass.USAGE_EMPTY,
1953 getClassTypeName(classDoc)
1954 + " " + classDoc.qualifiedName() + " is not used by any class in this documentation set.");
1956 printNavBarBottom(output, "uses", classDoc);
1962 private void printSuperTreeRec(HtmlPage output, ListIterator it, int level)
1964 if (it.hasPrevious()) {
1965 ClassDoc cd = (ClassDoc)it.previous();
1966 output.beginElement("li", new String[] { "class" }, new String[] { "inheritance " + level });
1967 output.beginElement("code");
1968 if (it.hasPrevious()) {
1969 printType(output, cd, true);
1972 output.print(cd.qualifiedName() + getTypeParameters(cd));
1974 output.endElement("code");
1975 output.endElement("li");
1977 output.beginElement("li");
1979 if (it.hasPrevious()) {
1980 output.beginElement("ul", new String[] { "class" }, new String[] { "inheritance " + (level + 1) });
1981 printSuperTreeRec(output, it, level + 1);
1982 output.endElement("ul");
1985 output.endElement("li");
1989 private static boolean isSubInterface(ClassDoc classDoc, ClassDoc otherClassDoc)
1991 ClassDoc[] interfaces = otherClassDoc.interfaces();
1992 for (int i=0; i<interfaces.length; ++i) {
1993 if (classDoc == interfaces[i]) {
1996 else if (isSubInterface(classDoc, interfaces[i])) {
2003 private void printCommaSeparatedTypes(HtmlPage output,
2008 if (!list.isEmpty()) {
2009 output.beginDiv(cssClass);
2010 output.div(CssClass.CLASS_KNOWNIMPLEMENTING_HEADER, header);
2011 output.beginDiv(CssClass.CLASS_KNOWNIMPLEMENTING_ITEM);
2012 Iterator it = list.iterator();
2013 while (it.hasNext()) {
2014 Type type = (Type)it.next();
2015 printType(output, type);
2020 output.endDiv(CssClass.CLASS_KNOWNIMPLEMENTING_ITEM);
2021 output.endDiv(cssClass);
2025 private void printClassPage(File packageDir, String pathToRoot,
2026 ClassDoc classDoc, ClassDoc prevClassDoc, ClassDoc nextClassDoc)
2029 HtmlPage output = newHtmlPage(new File(packageDir,
2030 classDoc.name() + filenameExtension),
2032 Set keywords = new LinkedHashSet();
2034 keywords.add(classDoc.qualifiedName() + " class");
2035 FieldDoc[] fieldDocs = classDoc.fields();
2036 for (int i=0; i<fieldDocs.length; ++i) {
2037 FieldDoc fieldDoc = fieldDocs[i];
2038 keywords.add(fieldDoc.name());
2041 MethodDoc[] methodDocs = classDoc.methods();
2042 for (int i=0; i<methodDocs.length; ++i) {
2043 MethodDoc methodDoc = methodDocs[i];
2044 keywords.add(methodDoc.name() + "()");
2047 String parameters = getTypeParameters(classDoc);
2049 output.beginPage(getPageTitle(classDoc.name()), getOutputCharset(),
2050 keywords, getStylesheets());
2051 output.beginBody(CssClass.BODY_CONTENT_CLASS);
2052 printNavBarTop(output, "class", classDoc, prevClassDoc, nextClassDoc);
2054 output.beginDiv(CssClass.CLASS_TITLE);
2055 output.div(CssClass.CLASS_TITLE_PACKAGE,
2056 classDoc.containingPackage().name());
2057 output.div(CssClass.CLASS_TITLE_CLASS,
2058 getClassTypeName(classDoc)
2059 + " " + classDoc.name()
2061 output.endDiv(CssClass.CLASS_TITLE);
2063 boolean needSep = false;
2065 if (classDoc.isInterface()) {
2067 InterfaceRelation relation
2068 = (InterfaceRelation)getInterfaceRelations().get(classDoc);
2070 printCommaSeparatedTypes(output,
2071 relation.superInterfaces,
2072 "All Superinterfaces:",
2073 CssClass.CLASS_KNOWNIMPLEMENTING);
2075 printCommaSeparatedTypes(output,
2076 relation.subInterfaces,
2077 "Known Subinterfaces:",
2078 CssClass.CLASS_KNOWNIMPLEMENTING);
2080 printCommaSeparatedTypes(output,
2081 relation.implementingClasses,
2082 "Known Implementing Classes:",
2083 CssClass.CLASS_KNOWNIMPLEMENTING);
2085 needSep = !relation.superInterfaces.isEmpty()
2086 || !relation.subInterfaces.isEmpty()
2087 || !relation.implementingClasses.isEmpty();
2092 if (!"java.lang.Object".equals(classDoc.qualifiedName())) {
2093 LinkedList superClasses = new LinkedList();
2094 for (ClassDoc cd = classDoc; cd != null; cd = cd.superclass()) {
2095 superClasses.add(cd);
2097 output.beginDiv(CssClass.CLASS_INHERITANCETREE);
2098 output.beginElement("ul", new String[] { "class" }, new String[] { "inheritance 0" });
2099 printSuperTreeRec(output, superClasses.listIterator(superClasses.size()), 0);
2100 output.endElement("ul");
2101 output.endDiv(CssClass.CLASS_INHERITANCETREE);
2103 if (null != classDoc.containingClass()) {
2104 output.beginDiv(CssClass.CLASS_ENCLOSINGCLASS);
2105 output.div(CssClass.CLASS_ENCLOSINGCLASS_HEADER, "Enclosing Class:");
2106 output.beginDiv(CssClass.CLASS_ENCLOSINGCLASS_ITEM);
2107 printType(output, classDoc.containingClass());
2108 output.endDiv(CssClass.CLASS_ENCLOSINGCLASS_ITEM);
2109 output.endDiv(CssClass.CLASS_ENCLOSINGCLASS);
2112 Set implementedInterfaces = getImplementedInterfaces(classDoc);
2114 printCommaSeparatedTypes(output,
2115 implementedInterfaces,
2116 "Implemented Interfaces:",
2117 CssClass.CLASS_KNOWNIMPLEMENTING);
2119 List knownDirectSubclasses = getKnownDirectSubclasses(classDoc);
2120 if (!knownDirectSubclasses.isEmpty()) {
2121 output.beginDiv(CssClass.CLASS_SUBCLASSES);
2122 output.div(CssClass.CLASS_SUBCLASSES_HEADER, "Known Direct Subclasses:");
2123 output.beginDiv(CssClass.CLASS_SUBCLASSES_ITEM);
2124 Iterator it = knownDirectSubclasses.iterator();
2125 while (it.hasNext()) {
2126 printType(output, (ClassDoc)it.next());
2132 output.endDiv(CssClass.CLASS_SUBCLASSES_ITEM);
2133 output.endDiv(CssClass.CLASS_SUBCLASSES_HEADER);
2134 output.endDiv(CssClass.CLASS_SUBCLASSES);
2143 output.beginDiv(CssClass.CLASS_SYNOPSIS);
2144 output.beginDiv(CssClass.CLASS_SYNOPSIS_DECLARATION);
2145 output.print(getFullModifiers(classDoc) + ' ' + getClassTypeKeyword(classDoc)
2147 output.beginSpan(CssClass.CLASS_SYNOPSIS_NAME);
2148 if (optionLinkSource.getValue() && null != classDoc.position()) {
2149 output.beginAnchor(getOuterClassDoc(classDoc).name() + "-source" + filenameExtension + "#line." + classDoc.position());
2150 output.print(classDoc.name() + parameters);
2154 output.print(classDoc.name() + parameters);
2156 output.endSpan(CssClass.CLASS_SYNOPSIS_NAME);
2157 output.endDiv(CssClass.CLASS_SYNOPSIS_DECLARATION);
2159 if (!classDoc.isInterface()) {
2160 if (null != classDoc.superclass()) {
2161 output.beginDiv(CssClass.CLASS_SYNOPSIS_SUPERCLASS);
2162 output.print("extends ");
2163 printType(output, classDoc.superclass());
2164 output.endDiv(CssClass.CLASS_SYNOPSIS_SUPERCLASS);
2168 ClassDoc[] interfaces = classDoc.interfaces();
2169 if (interfaces.length > 0) {
2170 output.beginDiv(CssClass.CLASS_SYNOPSIS_IMPLEMENTS);
2171 if (!classDoc.isInterface()) {
2172 output.print("implements ");
2175 output.print("extends ");
2177 for (int i=0; i<interfaces.length; ++i) {
2181 printType(output, interfaces[i]);
2183 output.endDiv(CssClass.CLASS_SYNOPSIS_IMPLEMENTS);
2185 output.endDiv(CssClass.CLASS_SYNOPSIS);
2189 if (!optionNoComment.getValue()) {
2190 output.beginDiv(CssClass.CLASS_DESCRIPTION);
2191 printTags(output, classDoc, classDoc.inlineTags(), false);
2192 output.endDiv(CssClass.CLASS_DESCRIPTION);
2194 printTaglets(output, classDoc.tags(), new HtmlTagletContext(classDoc, output, false));
2198 Set implementedInterfaces = getImplementedInterfaces(classDoc);
2200 boolean haveInheritedFields = false;
2201 boolean haveInheritedMethods = false;
2202 boolean haveInheritedClasses = false;
2204 if (!classDoc.isInterface()) {
2205 ClassDoc superClassDoc = classDoc.superclass();
2206 while (null != superClassDoc
2207 && (!haveInheritedFields
2208 || !haveInheritedMethods
2209 || !haveInheritedClasses)) {
2210 if (superClassDoc.fields().length > 0) {
2211 haveInheritedFields = true;
2213 if (superClassDoc.methods().length > 0) {
2214 haveInheritedMethods = true;
2216 if (superClassDoc.innerClasses().length > 0) {
2217 haveInheritedClasses = true;
2219 superClassDoc = superClassDoc.superclass();
2224 printProgramElementDocs(output, getSortedInnerClasses(classDoc),
2225 "Nested Class Summary", haveInheritedClasses,
2229 ClassDoc superClassDoc = classDoc.superclass();
2230 while (null != superClassDoc) {
2231 printInheritedMembers(output, getSortedInnerClasses(superClassDoc),
2232 "Nested classes/interfaces inherited from class {0}",
2234 superClassDoc = superClassDoc.superclass();
2238 printProgramElementDocs(output, getSortedFields(classDoc),
2239 "Field Summary", haveInheritedFields,
2243 ClassDoc superClassDoc = classDoc.superclass();
2244 while (null != superClassDoc) {
2245 printInheritedMembers(output, getSortedFields(superClassDoc),
2246 "Fields inherited from class {0}",
2248 superClassDoc = superClassDoc.superclass();
2253 Iterator it = implementedInterfaces.iterator();
2254 while (it.hasNext()) {
2255 ClassDoc implementedInterface
2256 = (ClassDoc)it.next();
2257 if (!"java.io.Serializable".equals(implementedInterface.qualifiedName())
2258 && !"java.io.Externalizable".equals(implementedInterface.qualifiedName())) {
2259 printInheritedMembers(output, getSortedFields(implementedInterface),
2260 "Fields inherited from interface {0}",
2261 implementedInterface);
2266 printProgramElementDocs(output, getSortedConstructors(classDoc),
2267 "Constructor Summary", false,
2268 "summary-constructors");
2269 printProgramElementDocs(output, getSortedMethods(classDoc),
2270 "Method Summary", haveInheritedMethods,
2273 if (classDoc.isInterface()) {
2274 InterfaceRelation relation
2275 = (InterfaceRelation)getInterfaceRelations().get(classDoc);
2276 Iterator it = relation.superInterfaces.iterator();
2277 while (it.hasNext()) {
2278 ClassDoc superClassDoc = (ClassDoc)it.next();
2279 printInheritedMembers(output, getSortedMethods(superClassDoc),
2280 "Methods inherited from interface {0}",
2285 ClassDoc superClassDoc = classDoc.superclass();
2286 while (null != superClassDoc) {
2287 printInheritedMembers(output, getSortedMethods(superClassDoc),
2288 "Methods inherited from class {0}",
2290 superClassDoc = superClassDoc.superclass();
2294 printMemberDetails(output, getSortedFields(classDoc),
2295 "Field Details", false, "detail-fields");
2296 printMemberDetails(output, getSortedConstructors(classDoc),
2297 "Constructor Details", false, "detail-constructors");
2298 printMemberDetails(output, getSortedMethods(classDoc),
2299 "Method Details", false, "detail-methods");
2301 printNavBarBottom(output, "class", classDoc);
2308 private void printInheritedMembers(HtmlPage output,
2309 ProgramElementDoc[] memberDocs,
2310 String headerFormat,
2311 ClassDoc superclass)
2313 if (memberDocs.length > 0) {
2315 output.beginDiv(CssClass.TABLE_CONTAINER);
2316 output.beginTable(CssClass.CLASS_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
2317 String superclassLink;
2318 if (superclass.isIncluded()) {
2319 superclassLink = superclass.containingPackage().name()
2320 + "." + createTypeHref(output, superclass, false);
2323 superclassLink = createTypeHref(output, superclass, true);
2325 output.rowDiv(CssClass.TABLE_SUB_HEADER,
2326 new MessageFormat(headerFormat).format(new Object[] {
2331 output.beginCell(CssClass.CLASS_SUMMARY_INHERITED);
2332 for (int i=0; i<memberDocs.length; ++i) {
2333 ProgramElementDoc memberDoc = memberDocs[i];
2337 String title = null;
2338 if (memberDoc.isMethod()) {
2339 title = memberDoc.name() + ((MethodDoc)memberDoc).flatSignature();
2341 else if (memberDoc.isInterface()) {
2342 title = "interface " + ((ClassDoc)memberDoc).qualifiedName();
2344 else if (memberDoc.isClass()) {
2345 title = "class " + ((ClassDoc)memberDoc).qualifiedName();
2347 output.beginAnchor(getMemberDocURL(output, memberDoc), title);
2348 output.beginSpan(CssClass.CLASS_SUMMARY_INHERITED_MEMBER);
2349 output.print(memberDoc.name());
2350 output.endSpan(CssClass.CLASS_SUMMARY_INHERITED_MEMBER);
2356 output.endDiv(CssClass.TABLE_CONTAINER);
2360 private void collectSpecifiedByRecursive(Set specifyingInterfaces,
2362 MethodDoc methodDoc)
2364 ClassDoc[] interfaces = classDoc.interfaces();
2365 for (int i=0; i<interfaces.length; ++i) {
2366 MethodDoc[] methods = interfaces[i].methods();
2367 for (int j=0; j<methods.length; ++j) {
2368 if (methods[j].name().equals(methodDoc.name())
2369 && methods[j].signature().equals(methodDoc.signature())) {
2370 specifyingInterfaces.add(methods[j]);
2374 collectSpecifiedByRecursive(specifyingInterfaces,
2380 private void printMemberDetails(HtmlPage output,
2381 ProgramElementDoc[] memberDocs, String header,
2382 boolean isOnSerializedPage,
2385 if (memberDocs.length > 0) {
2387 if (null != anchor) {
2388 output.anchorName(anchor);
2391 CssClass sectionClass;
2392 CssClass headerClass;
2393 if (isOnSerializedPage) {
2394 sectionClass = CssClass.SERIALIZED_SECTION;
2395 headerClass = CssClass.SERIALIZED_SECTION_HEADER;
2398 sectionClass = CssClass.SECTION;
2399 headerClass = CssClass.SECTION_HEADER;
2401 output.div(headerClass, header);
2402 output.beginDiv(sectionClass);
2404 for (int i=0; i<memberDocs.length; ++i) {
2409 ProgramElementDoc memberDoc = memberDocs[i];
2411 output.anchorName(getMemberAnchor(memberDoc));
2413 output.beginDiv(CssClass.MEMBER_DETAIL);
2414 output.div(CssClass.MEMBER_DETAIL_NAME, memberDoc.name());
2416 StringBuffer synopsis = new StringBuffer();
2417 int synopsisLength = 0;
2419 if (!isOnSerializedPage || !memberDoc.isField()) {
2420 String fullModifiers = getFullModifiers(memberDoc);
2421 synopsis.append(fullModifiers);
2422 synopsisLength += fullModifiers.length();
2425 if (memberDoc.isMethod() || memberDoc.isField()) {
2427 if (memberDoc.isMethod()) {
2428 type = ((MethodDoc)memberDoc).returnType();
2431 type = ((FieldDoc)memberDoc).type();
2434 synopsis.append(" ");
2436 synopsis.append(createTypeHref(output, type, false));
2437 if (null != type.asClassDoc() && type.asClassDoc().isIncluded()) {
2438 synopsisLength += type.asClassDoc().name().length();
2441 synopsisLength += type.qualifiedTypeName().length();
2443 synopsisLength += type.dimension().length();
2446 synopsis.append(" ");
2449 if (optionLinkSource.getValue() && null != memberDoc.position()) {
2450 ClassDoc containingClass = memberDoc.containingClass();
2451 while (null != containingClass.containingClass()) {
2452 containingClass = containingClass.containingClass();
2454 String href = containingClass.name() + "-source" + filenameExtension + "#line." + memberDoc.position().line();
2455 synopsis.append(output.createHrefString(href, memberDoc.name()));
2458 synopsis.append(memberDoc.name());
2460 synopsisLength += memberDoc.name().length();
2462 if (memberDoc.isConstructor() || memberDoc.isMethod()) {
2463 //printParameters(output, (ExecutableMemberDoc)memberDoc);
2464 synopsis.append("(");
2466 StringBuffer paddingLeft = new StringBuffer();
2467 for (int j=0; j<synopsisLength; ++j) {
2468 paddingLeft.append(' ');
2470 Parameter[] parameters = ((ExecutableMemberDoc)memberDoc).parameters();
2471 for (int j=0; j<parameters.length; ++j) {
2472 Parameter parameter = parameters[j];
2473 synopsis.append(createTypeHref(output, parameter.type(), false));
2474 synopsis.append(" ");
2475 synopsis.append(parameter.name());
2476 if (j < parameters.length - 1) {
2477 synopsis.append(",\n");
2478 synopsis.append(paddingLeft);
2481 synopsis.append(")");
2482 ClassDoc[] exceptions = ((ExecutableMemberDoc)memberDoc).thrownExceptions();
2483 if (exceptions.length > 0) {
2484 synopsis.append("\n throws ");
2485 for (int j=0; j<exceptions.length; ++j) {
2486 ClassDoc exception = exceptions[j];
2487 synopsis.append(createTypeHref(output, exception, false));
2488 if (j < exceptions.length - 1) {
2489 synopsis.append(",\n ");
2495 output.beginDiv(CssClass.MEMBER_DETAIL_SYNOPSIS);
2496 output.print(synopsis.toString());
2497 output.endDiv(CssClass.MEMBER_DETAIL_SYNOPSIS);
2499 output.beginDiv(CssClass.MEMBER_DETAIL_BODY);
2501 Tag[] deprecatedTags = memberDoc.tags("deprecated");
2502 if (deprecatedTags.length > 0) {
2503 output.beginDiv(CssClass.DEPRECATED_INLINE);
2504 output.beginSpan(CssClass.DEPRECATED_HEADER);
2505 output.print("Deprecated. ");
2506 output.endSpan(CssClass.DEPRECATED_HEADER);
2507 output.beginSpan(CssClass.DEPRECATED_BODY);
2509 for (int j=0; j<deprecatedTags.length; ++j) {
2510 printTags(output, memberDoc, deprecatedTags[j].inlineTags(), true);
2512 if (deprecatedTags.length > 0) {
2513 output.endSpan(CssClass.DEPRECATED_BODY);
2514 output.beginDiv(CssClass.DEPRECATED_INLINE);
2517 output.beginDiv(CssClass.MEMBER_DETAIL_DESCRIPTION);
2518 printTags(output, memberDoc, memberDoc.inlineTags(), false);
2519 output.endDiv(CssClass.MEMBER_DETAIL_DESCRIPTION);
2521 if (memberDoc.isConstructor() || memberDoc.isMethod()) {
2523 if (memberDoc.isMethod()) {
2524 Set specifyingInterfaces = new LinkedHashSet();
2525 if (memberDoc.containingClass().isInterface()) {
2526 collectSpecifiedByRecursive(specifyingInterfaces,
2527 memberDoc.containingClass(),
2528 (MethodDoc)memberDoc);
2531 for (ClassDoc cd = memberDoc.containingClass();
2532 null != cd; cd = cd.superclass()) {
2533 collectSpecifiedByRecursive(specifyingInterfaces,
2535 (MethodDoc)memberDoc);
2539 if (!specifyingInterfaces.isEmpty()
2540 && !isOnSerializedPage) {
2541 output.beginDiv(CssClass.MEMBER_DETAIL_SPECIFIED_BY_LIST);
2542 output.div(CssClass.MEMBER_DETAIL_SPECIFIED_BY_HEADER, "Specified by:");
2543 Iterator it = specifyingInterfaces.iterator();
2544 while (it.hasNext()) {
2545 MethodDoc specifyingInterfaceMethod = (MethodDoc)it.next();
2546 output.beginDiv(CssClass.MEMBER_DETAIL_SPECIFIED_BY_ITEM);
2547 output.beginAnchor(getMemberDocURL(output,
2548 specifyingInterfaceMethod));
2549 output.print(memberDoc.name());
2551 output.print(" in interface ");
2552 printType(output, specifyingInterfaceMethod.containingClass());
2553 output.endDiv(CssClass.MEMBER_DETAIL_SPECIFIED_BY_ITEM);
2555 output.endDiv(CssClass.MEMBER_DETAIL_SPECIFIED_BY_LIST);
2558 ClassDoc overriddenClassDoc = null;
2559 MemberDoc specifyingSuperMethod = null;
2561 for (ClassDoc superclassDoc = memberDoc.containingClass().superclass();
2562 null != superclassDoc && null == overriddenClassDoc;
2563 superclassDoc = superclassDoc.superclass()) {
2565 MethodDoc[] methods = superclassDoc.methods();
2566 for (int j=0; j<methods.length; ++j) {
2567 if (methods[j].name().equals(memberDoc.name())
2568 && methods[j].signature().equals(((MethodDoc)memberDoc).signature())) {
2569 overriddenClassDoc = superclassDoc;
2570 specifyingSuperMethod = methods[j];
2576 if (null != overriddenClassDoc) {
2577 output.beginDiv(CssClass.MEMBER_DETAIL_OVERRIDDEN_LIST);
2578 output.div(CssClass.MEMBER_DETAIL_OVERRIDDEN_HEADER, "Overrides:");
2579 output.beginDiv(CssClass.MEMBER_DETAIL_OVERRIDDEN_ITEM);
2581 output.beginAnchor(getMemberDocURL(output,
2582 specifyingSuperMethod));
2583 output.print(memberDoc.name());
2585 output.print(" in interface ");
2586 printType(output, overriddenClassDoc);
2588 output.endDiv(CssClass.MEMBER_DETAIL_OVERRIDDEN_ITEM);
2589 output.endDiv(CssClass.MEMBER_DETAIL_OVERRIDDEN_LIST);
2593 if (!optionNoComment.getValue()) {
2595 ExecutableMemberDoc execMemberDoc
2596 = (ExecutableMemberDoc)memberDoc;
2598 if (execMemberDoc.paramTags().length > 0) {
2599 output.beginDiv(CssClass.MEMBER_DETAIL_PARAMETER_LIST);
2600 output.div(CssClass.MEMBER_DETAIL_PARAMETER_HEADER, "Parameters:");
2601 Parameter[] parameters = execMemberDoc.parameters();
2602 for (int j=0; j<parameters.length; ++j) {
2603 Parameter parameter = parameters[j];
2604 ParamTag[] paramTags = execMemberDoc.paramTags();
2605 ParamTag paramTag = null;
2606 for (int k=0; k<paramTags.length; ++k) {
2607 if (paramTags[k].parameterName().equals(parameter.name())) {
2608 paramTag = paramTags[k];
2613 if (null != paramTag) {
2614 output.beginDiv(CssClass.MEMBER_DETAIL_PARAMETER_ITEM);
2615 output.beginSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_NAME);
2616 output.print(parameter.name());
2617 output.endSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_NAME);
2618 output.beginSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_SEPARATOR);
2619 output.print(" - ");
2620 output.endSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_SEPARATOR);
2621 output.beginSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_DESCRIPTION);
2622 printTags(output, execMemberDoc, paramTag.inlineTags(), false);
2623 output.endSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_DESCRIPTION);
2624 output.endDiv(CssClass.MEMBER_DETAIL_PARAMETER_ITEM);
2627 output.endDiv(CssClass.MEMBER_DETAIL_PARAMETER_LIST);
2630 if (execMemberDoc.isMethod()
2631 && !"void".equals(((MethodDoc)execMemberDoc).returnType().typeName())) {
2633 Tag[] returnTags = execMemberDoc.tags("return");
2634 if (returnTags.length > 0) {
2635 Tag returnTag = returnTags[0];
2637 output.beginDiv(CssClass.MEMBER_DETAIL_RETURN_LIST);
2638 output.div(CssClass.MEMBER_DETAIL_RETURN_HEADER, "Returns:");
2639 output.beginDiv(CssClass.MEMBER_DETAIL_RETURN_ITEM);
2641 printTags(output, execMemberDoc, returnTag.inlineTags(), false);
2643 output.endDiv(CssClass.MEMBER_DETAIL_RETURN_ITEM);
2644 output.endDiv(CssClass.MEMBER_DETAIL_RETURN_LIST);
2648 Set thrownExceptions = getThrownExceptions(execMemberDoc);
2649 boolean haveThrowsInfo = false;
2650 ThrowsTag[] throwsTags = execMemberDoc.throwsTags();
2651 for (int k=0; k<throwsTags.length; ++k) {
2652 ThrowsTag throwsTag = throwsTags[k];
2653 if (null != throwsTags[k].exception()
2654 && (isUncheckedException(throwsTags[k].exception())
2655 || thrownExceptions.contains(throwsTag.exception()))) {
2656 haveThrowsInfo = true;
2661 if (haveThrowsInfo) {
2662 output.beginDiv(CssClass.MEMBER_DETAIL_THROWN_LIST);
2663 output.div(CssClass.MEMBER_DETAIL_THROWN_HEADER, "Throws:");
2665 for (int k=0; k<throwsTags.length; ++k) {
2666 ThrowsTag throwsTag = throwsTags[k];
2667 if (null != throwsTag.exception()
2668 && (isUncheckedException(throwsTag.exception())
2669 || thrownExceptions.contains(throwsTag.exception()))) {
2670 output.beginDiv(CssClass.MEMBER_DETAIL_THROWN_ITEM);
2671 output.beginSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_NAME);
2672 printType(output, throwsTags[k].exception());
2673 output.endSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_NAME);
2674 if (null != throwsTag) {
2675 output.beginSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_SEPARATOR);
2676 output.print(" - ");
2677 output.endSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_SEPARATOR);
2678 output.beginSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_DESCRIPTION);
2679 printTags(output, execMemberDoc, throwsTag.inlineTags(), false);
2680 output.endSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_DESCRIPTION);
2682 output.endDiv(CssClass.MEMBER_DETAIL_THROWN_ITEM);
2685 output.endDiv(CssClass.MEMBER_DETAIL_THROWN_LIST);
2690 if (!optionNoComment.getValue()) {
2692 if (memberDoc.isField()) {
2693 FieldDoc fieldDoc = ((FieldDoc)memberDoc);
2694 if (null != fieldDoc.constantValue()) {
2695 output.beginDiv(CssClass.MEMBER_DETAIL_THROWN_LIST);
2696 output.div(CssClass.MEMBER_DETAIL_THROWN_HEADER, "Field Value:");
2697 output.div(CssClass.MEMBER_DETAIL_THROWN_ITEM,
2698 fieldDoc.constantValueExpression().toString());
2699 output.endDiv(CssClass.MEMBER_DETAIL_THROWN_LIST);
2703 TagletContext context = new HtmlTagletContext(memberDoc, output, isOnSerializedPage);
2704 printTaglets(output, memberDoc.tags(), context);
2707 output.endDiv(CssClass.MEMBER_DETAIL_BODY);
2708 output.endDiv(CssClass.MEMBER_DETAIL);
2710 output.endDiv(sectionClass);
2715 private void printParameters(HtmlPage output, ExecutableMemberDoc memberDoc)
2717 Parameter[] parameters = memberDoc.parameters();
2719 for (int j=0; j<parameters.length; ++j) {
2723 printType(output, parameters[j].type());
2724 output.print(" ");
2725 output.print(parameters[j].name());
2730 private void printProgramElementDocs(HtmlPage output,
2731 ProgramElementDoc[] memberDocs,
2733 boolean forceOutputHeader,
2736 if (memberDocs.length > 0 || forceOutputHeader) {
2737 output.anchorName(anchor);
2738 output.beginDiv(CssClass.TABLE_CONTAINER);
2739 output.beginTable(CssClass.CLASS_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
2740 output.rowDiv(CssClass.TABLE_HEADER, header);
2742 for (int i=0; i<memberDocs.length; ++i) {
2743 ProgramElementDoc memberDoc = memberDocs[i];
2746 if (!memberDoc.isConstructor()) {
2747 output.beginCell(CssClass.CLASS_SUMMARY_LEFT);
2748 output.beginDiv(CssClass.CLASS_SUMMARY_LEFT_SYNOPSIS);
2749 output.print(getSummaryModifiers(memberDoc) + " ");
2750 if (memberDoc.isMethod()) {
2751 printType(output, ((MethodDoc)memberDoc).returnType());
2753 else if (memberDoc.isField()) {
2754 printType(output, ((FieldDoc)memberDoc).type());
2756 else if (memberDoc.isInterface()) {
2757 output.print(" interface");
2759 else if (memberDoc.isClass()) {
2760 output.print(" class");
2762 output.endDiv(CssClass.CLASS_SUMMARY_LEFT_SYNOPSIS);
2766 output.beginCell(CssClass.CLASS_SUMMARY_RIGHT);
2767 output.beginDiv(CssClass.CLASS_SUMMARY_RIGHT_LIST);
2768 output.beginDiv(CssClass.CLASS_SUMMARY_RIGHT_SYNOPSIS);
2769 if (memberDoc.isClass() || memberDoc.isInterface()) {
2770 output.beginAnchor(getClassDocURL(output, (ClassDoc)memberDoc));
2773 output.beginAnchor("#" + getMemberAnchor(memberDoc));
2775 output.print(memberDoc.name());
2777 if (memberDoc.isConstructor() || memberDoc.isMethod()) {
2778 printParameters(output, (ExecutableMemberDoc)memberDoc);
2780 output.endDiv(CssClass.CLASS_SUMMARY_RIGHT_SYNOPSIS);
2781 Tag[] firstSentenceTags;
2782 Tag[] deprecatedTags = memberDoc.tags("deprecated");
2783 if (deprecatedTags.length > 0) {
2784 firstSentenceTags = deprecatedTags[0].firstSentenceTags();
2787 firstSentenceTags = memberDoc.firstSentenceTags();
2790 if (null != firstSentenceTags && firstSentenceTags.length > 0) {
2791 output.beginDiv(CssClass.CLASS_SUMMARY_RIGHT_DESCRIPTION);
2792 if (deprecatedTags.length > 0) {
2793 output.beginDiv(CssClass.DEPRECATED);
2794 output.beginSpan(CssClass.DEPRECATED_HEADER);
2795 output.print("Deprecated. ");
2796 output.endSpan(CssClass.DEPRECATED_HEADER);
2797 output.beginSpan(CssClass.DEPRECATED_BODY);
2799 printTags(output, memberDoc, firstSentenceTags, true);
2800 if (deprecatedTags.length > 0) {
2801 output.endSpan(CssClass.DEPRECATED_BODY);
2802 output.beginDiv(CssClass.DEPRECATED);
2804 output.endDiv(CssClass.CLASS_SUMMARY_RIGHT_DESCRIPTION);
2806 output.endDiv(CssClass.CLASS_SUMMARY_RIGHT_LIST);
2811 output.endDiv(CssClass.TABLE_CONTAINER);
2815 private void printTag(final HtmlPage output,
2816 HtmlRepairer repairer,
2817 Tag tag, boolean firstSentence,
2821 TagletContext context = new HtmlTagletContext(contextDoc, output, false);
2822 if (firstSentence) {
2823 output.print(renderInlineTags(tag.firstSentenceTags(), context));
2826 output.print(renderInlineTags(tag.inlineTags(), context));
2830 private void printTags(HtmlPage output, Doc contextDoc, Tag[] tags, boolean firstSentence)
2832 printTags(output, contextDoc, tags, firstSentence, false);
2835 private void printTags(HtmlPage output, Doc contextDoc, Tag[] tags, boolean firstSentence, boolean inline)
2837 if (!optionNoComment.getValue()) {
2838 output.print(renderInlineTags(tags, new HtmlTagletContext(contextDoc, output, false)));
2842 if (!optionNoComment.getValue()) {
2843 output.print(renderInlineTags(tag.firstSentenceTags(), output));
2844 HtmlRepairer repairer = new HtmlRepairer(getRootDoc(),
2848 for (int i=0; i<tags.length; ++i) {
2849 printTag(output, repairer, tags[i], firstSentence, inline);
2851 output.print(repairer.terminateText());
2856 private String getClassDocURL(HtmlPage output, ClassDoc classDoc)
2858 return output.getPathToRoot()
2860 + getPackageURL(classDoc.containingPackage())
2861 + classDoc.name() + filenameExtension;
2864 private String getMemberDocURL(HtmlPage output, ProgramElementDoc memberDoc)
2866 ClassDoc classDoc = memberDoc.containingClass();
2867 PackageDoc packageDoc = classDoc.containingPackage();
2868 ExternalDocSet externalDocSet = null;
2869 if (classDoc.containingPackage().name().length() > 0) {
2870 externalDocSet = packageNameToDocSet.get(packageDoc.name());
2872 StringBuffer result = new StringBuffer();
2873 result.append(getClassDocURL(output, classDoc));
2875 if (null == externalDocSet) {
2876 result.append(getMemberAnchor(memberDoc));
2879 result.append(getMemberAnchor(memberDoc, externalDocSet.isJavadocCompatible()));
2881 return result.toString();
2884 private void printType(HtmlPage output, Type type)
2886 printType(output, type, false);
2889 private void printType(HtmlPage output, Type type, boolean fullyQualified)
2891 output.print(createTypeHref(output, type, fullyQualified));
2894 private String createTypeHref(HtmlPage output, Type type, boolean fullyQualified)
2896 ClassDoc asClassDoc = type.asClassDoc();
2898 if (null != asClassDoc && asClassDoc.isIncluded()) {
2899 url = getClassDocURL(output, asClassDoc);
2901 else if (!type.isPrimitive()) {
2902 if (type.qualifiedTypeName().length() > type.typeName().length()) {
2903 String packageName = type.qualifiedTypeName();
2904 packageName = packageName.substring(0, packageName.length() - type.typeName().length() - 1);
2906 ExternalDocSet externalDocSet = packageNameToDocSet.get(packageName);
2907 if (null != externalDocSet) {
2908 url = externalDocSet.getClassDocURL(packageName, type.typeName());
2913 StringBuffer result = new StringBuffer();
2915 if (null != url && null != asClassDoc) {
2916 String parameters = getTypeParameters(asClassDoc);
2917 if (fullyQualified) {
2918 result.append(output.createHrefString(url,possiblyQualifiedName(asClassDoc) + parameters));
2921 StringBuffer title = new StringBuffer();
2922 title.append(getClassTypeName(asClassDoc));
2923 title.append(" in ");
2924 title.append(asClassDoc.containingPackage().name());
2925 result.append(output.createHrefString(url, asClassDoc.name() + parameters, title.toString()));
2929 result.append(possiblyQualifiedName(type));
2931 result.append(type.dimension());
2932 return result.toString();
2935 private void printTaglets(final HtmlPage output, Tag[] tags, TagletContext context)
2937 super.printMainTaglets(tags, context, new TagletPrinter() {
2938 public void printTagletString(String tagletString) {
2939 output.beginDiv(CssClass.TAGLET);
2940 output.print(tagletString);
2941 output.endDiv(CssClass.TAGLET);
2946 private String getPackageURL(PackageDoc packageDoc)
2948 if (packageDoc.name().length() > 0) {
2949 ExternalDocSet externalDocSet = packageNameToDocSet.get(packageDoc.name());
2951 if (null != externalDocSet) {
2952 url = externalDocSet.getPackageDocURL(packageDoc.name());
2955 url = packageDoc.name().replace('.', '/');
2957 if (!url.endsWith("/")) {
2969 private String getClassURL(ClassDoc classDoc)
2971 ExternalDocSet externalDocSet = null;
2972 if (classDoc.containingPackage().name().length() > 0) {
2973 externalDocSet = packageNameToDocSet.get(classDoc.containingPackage().name());
2975 if (null != externalDocSet) {
2976 return externalDocSet.getClassDocURL(classDoc.containingPackage().name(),
2980 return getPackageURL(classDoc.containingPackage()) + classDoc.name() + filenameExtension;
2984 protected void run()
2985 throws DocletConfigurationException, IOException
2987 if (optionSerialWarn.getValue()) {
2988 printWarning("Option -serialwarn is currently ignored.");
2991 if (null != optionTitle.getValue()) {
2992 printWarning("Option -title is deprecated.");
2995 if (!optionValidHtml.getValue()) {
2996 printWarning("Option -validhtml hasn't been specified. Generated HTML will not validate.");
3001 boolean warningEmitted = false;
3002 Iterator it = externalDocSets.iterator();
3003 while (it.hasNext()) {
3004 ExternalDocSet externalDocSet = (ExternalDocSet)it.next();
3005 printNotice("Fetching package list for external documentation set.");
3007 externalDocSet.load(getTargetDirectory());
3008 if (!isJavadocCompatibleNames() && externalDocSet.isJavadocCompatible()
3009 && !warningEmitted) {
3010 printWarning("Linking to javadoc-compatible documentation. Generated HTML will not validate ");
3011 warningEmitted = true;
3014 catch (FileNotFoundException e) {
3015 printWarning("Cannot fetch package list from " + externalDocSet.getPackageListDir());
3017 Iterator pit = externalDocSet.getPackageNames().iterator();
3018 while (pit.hasNext()) {
3019 String packageName = (String)pit.next();
3020 packageNameToDocSet.put(packageName, externalDocSet);
3024 printNotice("Building cross-reference information...");
3025 getInterfaceRelations();
3028 printNotice("Writing overview files...");
3029 printFrameSetPage();
3030 if (!isSinglePackage()) {
3031 printPackagesMenuPage();
3032 printAllClassesMenuPage();
3033 printOverviewPage();
3034 if (!optionNoTree.getValue()) {
3035 printNotice("Writing full tree...");
3036 printFullTreePage();
3039 printPackagesListFile();
3041 if (!optionNoIndex.getValue()) {
3042 printNotice("Writing index...");
3043 if (!optionSplitIndex.getValue()) {
3050 if (outputHelpPage && !optionNoHelp.getValue()) {
3056 File resourcesDir = new File(getTargetDirectory(),
3059 if ((resourcesDir.exists() && !resourcesDir.isDirectory())
3060 || (!resourcesDir.exists() && !resourcesDir.mkdirs())) {
3061 throw new IOException("Cannot create directory " + resourcesDir);
3066 String[] resourceNames = {
3068 "gjdochtml-clean-layout.css",
3069 "gjdochtml-clean-color1.css",
3071 "xhtml11-target10.dtd",
3074 for (int i=0; i<resourceNames.length; ++i) {
3075 String resourceName = resourceNames[i];
3076 File targetFile = new File(resourcesDir,
3078 InputStream in = getClass().getResourceAsStream("/htmldoclet/" + resourceName);
3080 in = new FileInputStream("src/resources/htmldoclet/" + resourceName);
3082 FileOutputStream out = new FileOutputStream(targetFile);
3083 IOToolkit.copyStream(in, out);
3090 if (null != optionAddStylesheet.getValue()) {
3091 File addStylesheetTargetFile = new File(resourcesDir,
3094 IOToolkit.copyFile(optionAddStylesheet.getValue(),
3095 addStylesheetTargetFile);
3098 if (null != optionStylesheetFile.getValue()) {
3099 File stylesheetTargetFile = new File(resourcesDir,
3102 IOToolkit.copyFile(optionStylesheetFile.getValue(),
3103 stylesheetTargetFile);
3106 // Write gjdoc.properties
3108 File gjdocPropertiesTargetFile = new File(getTargetDirectory(),
3109 "gjdoc.properties");
3110 writeGjdocProperties(gjdocPropertiesTargetFile);
3114 InputStream cssIn = getClass().getResourceAsStream("/htmldoclet/gjdochtml-vanilla.css");
3115 FileOutputStream cssOut = new FileOutputStream(stylesheetTargetFile);
3116 IOToolkit.copyStream(cssIn, cssOut);
3122 if (!optionNoDeprecatedList.getValue()) {
3123 printDeprecationPage();
3126 printSerializationPage();
3128 Collection packageDocsCollection = getAllPackages();
3129 PackageDoc[] packageDocs
3130 = (PackageDoc[])packageDocsCollection.toArray(new PackageDoc[0]);
3132 for (int i=0; i<packageDocs.length; ++i) {
3133 PackageDoc packageDoc = packageDocs[i];
3134 File packageDir = new File(getTargetDirectory(),
3135 packageDoc.name().replace('.', File.separatorChar));
3136 if (!packageDir.exists() && !packageDir.mkdirs()) {
3137 throw new IOException("Couldn't create directory " + packageDir);
3140 List packageSourceDirs = getPackageSourceDirs(packageDoc);
3141 Iterator pdIt = packageSourceDirs.iterator();
3142 while (pdIt.hasNext()) {
3143 File sourcePackageDir = (File)pdIt.next();
3144 copyDocFiles(sourcePackageDir, packageDir);
3147 catch (IOException ignore) {
3149 String pathToRoot = getPathToRoot(packageDir, getTargetDirectory());
3150 String packageName = packageDoc.name();
3151 if (0 == packageName.length()) {
3152 packageName = "<unnamed>";
3154 printNotice("Writing HTML files for package " + packageName);
3155 printPackagePage(packageDir, pathToRoot, packageDoc,
3156 (i > 0) ? packageDocs[i - 1] : null,
3157 (i < packageDocs.length - 1) ? packageDocs[i + 1] : null);
3158 if (!optionNoTree.getValue()) {
3159 printPackageTreePage(packageDir, pathToRoot, packageDoc);
3161 printPackageClassesMenuPage(packageDir, pathToRoot, packageDoc);
3162 ClassDoc[] classDocs = packageDoc.allClasses();
3163 for (int j=0; j<classDocs.length; ++j) {
3164 ClassDoc classDoc = classDocs[j];
3165 if (classDoc.isIncluded()) {
3166 printClassPage(packageDir, pathToRoot,
3168 (j > 0) ? classDocs[j - 1] : null,
3169 (j < classDocs.length - 1) ? classDocs[j + 1] : null
3171 if (optionUse.getValue()) {
3172 printClassUsagePage(packageDir, pathToRoot, classDocs[j]);
3174 if (optionLinkSource.getValue() && null == classDoc.containingClass()) {
3176 File sourceFile = getSourceFile(classDoc);
3178 Java2xhtml java2xhtml = new Java2xhtml();
3179 Properties properties = new Properties();
3180 properties.setProperty("isCodeSnippet", "true");
3181 properties.setProperty("hasLineNumbers", "true");
3182 java2xhtml.setProperties(properties);
3184 StringWriter sourceBuffer = new StringWriter();
3185 FileReader sourceReader = new FileReader(sourceFile);
3186 IOToolkit.copyStream(sourceReader, sourceBuffer);
3187 sourceReader.close();
3188 String result = java2xhtml.makeHTML(sourceBuffer.getBuffer(), sourceFile.getName());
3190 printSourcePage(packageDir,
3194 catch (IOException e) {
3195 printWarning("Cannot locate source file for class " + classDoc.qualifiedTypeName());
3203 private String getPathToRoot(File subDir, File rootDir)
3205 StringBuffer result = new StringBuffer();
3206 while (!subDir.equals(rootDir)) {
3207 if (result.length() > 0) {
3210 subDir = subDir.getParentFile();
3211 result.append("..");
3213 if (0 == result.length()) {
3216 return result.toString();
3219 private String getClassTypeName(ClassDoc classDoc)
3221 if (classDoc.isInterface()) {
3229 private String getClassTypeKeyword(ClassDoc classDoc)
3231 if (classDoc.isInterface()) {
3239 private String getMemberAnchor(ProgramElementDoc memberDoc)
3241 return getMemberAnchor(memberDoc, isJavadocCompatibleNames());
3244 private String getMemberAnchor(ProgramElementDoc memberDoc, boolean javadocCompatibility)
3246 StringBuffer anchor = new StringBuffer();
3247 anchor.append(memberDoc.name());
3248 if (memberDoc.isConstructor() || memberDoc.isMethod()) {
3249 if (javadocCompatibility) {
3250 anchor.append(((ExecutableMemberDoc)memberDoc).signature());
3254 Parameter[] parameters = ((ExecutableMemberDoc)memberDoc).parameters();
3255 for (int i=0; i<parameters.length; ++i) {
3256 anchor.append(parameters[i].type().typeName());
3257 for (int j=0; j<parameters[i].type().dimension().length()/2; ++j) {
3260 if (i < parameters.length - 1) {
3266 return anchor.toString();
3269 private String getFullModifiers(ProgramElementDoc memberDoc)
3271 StringBuffer result = new StringBuffer();
3272 if (memberDoc.isPackagePrivate()) {
3273 result.append("(package private) ");
3275 result.append(memberDoc.modifiers());
3276 if ((memberDoc.isClass() && ((ClassDoc)memberDoc).isAbstract())
3277 || (memberDoc.isMethod() && ((MethodDoc)memberDoc).isAbstract())) {
3278 result.append(" abstract");
3280 return result.toString();
3283 private String getSummaryModifiers(ProgramElementDoc memberDoc)
3285 StringBuffer result = new StringBuffer();
3286 if (memberDoc.isPackagePrivate()) {
3287 result.append("(package private) ");
3289 else if (memberDoc.isPrivate()) {
3290 result.append("private ");
3292 else if (memberDoc.isProtected()) {
3293 result.append("protected ");
3295 if (memberDoc.isStatic()) {
3296 result.append("static");
3298 else if ((memberDoc.isClass() && ((ClassDoc)memberDoc).isAbstract())
3299 || (memberDoc.isMethod() && ((MethodDoc)memberDoc).isAbstract())) {
3300 result.append("abstract");
3302 return result.toString();
3305 protected DocletOption[] getOptions()
3310 private DocletOptionFlag optionNoNavBar =
3311 new DocletOptionFlag("-nonavbar");
3313 private DocletOptionFlag optionNoTree =
3314 new DocletOptionFlag("-notree");
3316 private DocletOptionFlag optionNoDeprecatedList =
3317 new DocletOptionFlag("-nodeprecatedlist");
3319 private DocletOptionFlag optionNoIndex =
3320 new DocletOptionFlag("-noindex");
3322 private DocletOptionFlag optionUse =
3323 new DocletOptionFlag("-use");
3325 private DocletOptionFlag optionNoHelp =
3326 new DocletOptionFlag("-nohelp");
3328 private DocletOptionFlag optionNoComment =
3329 new DocletOptionFlag("-nocomment");
3331 private DocletOptionFlag optionSerialWarn =
3332 new DocletOptionFlag("-serialwarn");
3334 private DocletOptionFlag optionSplitIndex =
3335 new DocletOptionFlag("-splitindex");
3337 private DocletOptionString optionHeader =
3338 new DocletOptionString("-header");
3340 private DocletOptionString optionFooter =
3341 new DocletOptionString("-footer");
3343 private DocletOptionString optionBottom =
3344 new DocletOptionString("-bottom");
3346 private DocletOptionString optionWindowTitle =
3347 new DocletOptionString("-windowtitle");
3349 private DocletOptionString optionDocTitle =
3350 new DocletOptionString("-doctitle");
3352 private DocletOptionString optionTitle =
3353 new DocletOptionString("-title");
3355 private DocletOptionFile optionHelpFile =
3356 new DocletOptionFile("-helpfile");
3358 private DocletOptionFile optionStylesheetFile =
3359 new DocletOptionFile("-stylesheetfile");
3361 private DocletOptionFlag optionLinkSource =
3362 new DocletOptionFlag("-linksource");
3364 private DocletOption optionLink =
3365 new DocletOption("-link") {
3367 public int getLength()
3372 public boolean set(String[] optionArr)
3374 externalDocSets.add(new ExternalDocSet(optionArr[1], null));
3379 private DocletOption optionLinkOffline =
3380 new DocletOption("-linkoffline") {
3382 public int getLength()
3387 public boolean set(String[] optionArr)
3389 externalDocSets.add(new ExternalDocSet(optionArr[1], optionArr[2]));
3394 private DocletOptionString optionDocEncoding =
3395 new DocletOptionString("-docencoding");
3397 private DocletOptionString optionEncoding =
3398 new DocletOptionString("-encoding");
3400 private DocletOptionString optionCharset =
3401 new DocletOptionString("-charset");
3403 private DocletOptionFile optionAddStylesheet =
3404 new DocletOptionFile("-addstylesheet");
3406 private DocletOptionFlag optionValidHtml =
3407 new DocletOptionFlag("-validhtml");
3409 private DocletOptionString optionBaseUrl =
3410 new DocletOptionString("-baseurl");
3412 private DocletOption[] options =
3416 optionNoDeprecatedList,
3426 optionStylesheetFile,
3436 optionAddStylesheet,
3442 setInstance(new HtmlDoclet());
3445 private static String replaceDocRoot(HtmlPage output, String str)
3447 return StringToolkit.replace(str, "{@docRoot}", output.getPathToRoot());
3450 private String getOutputDocEncoding()
3452 String encoding = optionDocEncoding.getValue();
3454 if (null == encoding) {
3455 encoding = optionEncoding.getValue();
3461 private String getOutputCharset()
3463 if (null == outputCharset) {
3465 if (null != optionCharset.getValue()) {
3466 outputCharset = optionCharset.getValue();
3469 String fileEncoding = System.getProperty("file.encoding");
3470 if (null != fileEncoding) {
3472 outputCharset = Charset.forName(fileEncoding).name();
3474 catch (Exception ignore) {
3478 if (null == outputCharset) {
3479 printWarning("Cannot determine platform default charset, falling back to ISO-8859-1.");
3480 outputCharset = "ISO-8859-1";
3484 return outputCharset;
3487 public InlineTagRenderer getInlineTagRenderer()
3492 public String renderInlineTags(Tag[] tags, TagletContext context)
3494 StringBuffer result = new StringBuffer();
3496 HtmlRepairer repairer = new HtmlRepairer(getRootDoc(),
3501 for (int i=0; i<tags.length; ++i) {
3505 if ("Text".equals(tag.name())) {
3506 result.append(repairer.getWellformedHTML(tag.text()));
3508 else if ("@link".equals(tag.name())) {
3509 result.append(renderSeeTag((SeeTag)tag, context, false));
3511 else if ("@linkplain".equals(tag.name())) {
3512 result.append(renderSeeTag((SeeTag)tag, context, true));
3514 else if ("@docRoot".equals(tag.name())) {
3515 result.append(((HtmlTagletContext)context).getOutput().getPathToRoot());
3518 //TagletContext context = TagletContext.OVERVIEW; // FIXME
3519 Taglet taglet = (Taglet)tagletMap.get(tag.name().substring(1));
3520 if (null != taglet) {
3521 if (taglet instanceof GnuExtendedTaglet) {
3522 result.append(((GnuExtendedTaglet)taglet).toString(tag, context));
3525 result.append(taglet.toString(tag));
3530 result.append(repairer.terminateText());
3531 return result.toString();
3534 public String renderSeeTag(SeeTag seeTag, TagletContext context, boolean plainFont)
3536 StringBuffer result = new StringBuffer();
3539 String label = null;
3540 MemberDoc referencedMember = seeTag.referencedMember();
3541 if (null != seeTag.referencedClass()) {
3543 href = getClassDocURL(((HtmlTagletContext)context).getOutput(), seeTag.referencedClass());
3545 Doc doc = context.getDoc();
3546 ClassDoc classDoc = null;
3547 if (doc.isClass() || doc.isInterface()) {
3548 classDoc = (ClassDoc)doc;
3550 else if (doc.isField() || doc.isMethod() || doc.isConstructor()) {
3551 classDoc = ((MemberDoc)doc).containingClass();
3554 if (null == referencedMember
3555 || seeTag.referencedClass() != classDoc
3556 || ((HtmlTagletContext)context).isOnSerializedPage()) {
3558 if (!seeTag.referencedClass().isIncluded()) {
3559 label = possiblyQualifiedName(seeTag.referencedClass());
3562 label = seeTag.referencedClass().typeName();
3564 if (null != referencedMember) {
3572 if (null != referencedMember) {
3573 label += referencedMember.name();
3574 if (referencedMember.isMethod() || referencedMember.isConstructor()) {
3575 label += ((ExecutableMemberDoc)referencedMember).flatSignature();
3577 href += '#' + getMemberAnchor(referencedMember);
3579 else if (null != seeTag.referencedMemberName()) {
3584 String referencedClassName = seeTag.referencedClassName();
3586 if (null != referencedClassName) {
3588 String referencedPackageName = null;
3590 Iterator it = packageNameToDocSet.keySet().iterator();
3591 while (it.hasNext()) {
3592 String packageName = (String)it.next();
3593 if ((null == referencedPackageName
3594 || packageName.length() > referencedPackageName.length())
3595 && referencedClassName.startsWith(packageName + '.')) {
3596 referencedPackageName = packageName;
3600 if (null != referencedPackageName) {
3601 ExternalDocSet externalDocSet
3602 = (ExternalDocSet)packageNameToDocSet.get(referencedPackageName);
3604 String className = referencedClassName.substring(referencedPackageName.length() + 1);
3605 href = externalDocSet.getClassDocURL(referencedPackageName,
3609 String referencedMemberName = seeTag.referencedMemberName();
3611 if (null != referencedMemberName) {
3613 label += referencedMemberName;
3614 href += '#' + transformReferencedMemberName(referencedMemberName,
3615 externalDocSet.isJavadocCompatible());
3617 else if (null != seeTag.referencedMemberName()) {
3624 if (null != seeTag.label()
3625 && seeTag.label().length() > 0) {
3626 label = seeTag.label();
3629 if (null == label) {
3630 label = seeTag.text();
3631 if (label.startsWith("#")) {
3632 label = label.substring(1);
3635 label = label.replace('#', '.');
3641 result.append("<a href=\"");
3642 result.append(href);
3643 result.append("\">");
3645 result.append("<code>");
3647 result.append(label);
3649 result.append("</code>");
3651 result.append("</a>");
3655 result.append("<code>");
3657 result.append(label);
3659 result.append("</code>");
3663 return result.toString();
3666 protected String renderTag(String tagName, Tag[] tags, TagletContext context)
3668 Doc doc = context.getDoc();
3670 if ("see".equals(tagName)
3671 && ((tags.length > 0)
3673 && (((ClassDoc)doc).isSerializable()
3674 || ((ClassDoc)doc).isExternalizable())))) {
3676 StringBuffer result = new StringBuffer();
3677 result.append("<dl class=\"tag list\">");
3678 result.append("<dt class=\"tag section header\"><b>");
3679 result.append("See Also:");
3680 result.append("</b></dt>");
3682 boolean oneLine = true;
3685 result.append("<dd>");
3688 for (int i = 0; i < tags.length; ++i) {
3691 result.append(", ");
3695 result.append("<dd>");
3697 result.append(renderSeeTag((SeeTag)tags[i], context, false));
3699 result.append("</dd>");
3703 if ((doc instanceof ClassDoc)
3704 && (((ClassDoc)doc).isSerializable() || ((ClassDoc)doc).isExternalizable())) {
3705 if (tags.length > 0) {
3706 result.append(", ");
3708 HtmlPage output = ((HtmlTagletContext)context).getOutput();
3709 result.append("<a href=\"" + output.getPathToRoot() + "/serialized-form" + filenameExtension + "#" + ((ClassDoc)doc).qualifiedName() + "\">Serialized Form</a>");
3713 result.append("</dd>");
3715 result.append("</dl>");
3716 return result.toString();
3718 else if (tags.length > 0
3719 && "serial".equals(tagName)
3720 && ((HtmlTagletContext)context).isOnSerializedPage()) {
3722 return renderInlineTags(tags[0].inlineTags(), context);
3729 private String getWindowTitle()
3731 if (null == optionWindowTitle.getValue()) {
3732 return "Generated API Documentation";
3735 return optionWindowTitle.getValue();
3739 private String getPageTitle(String title)
3741 if (null == optionWindowTitle.getValue()) {
3745 return title + " (" + optionWindowTitle.getValue() + ")";
3749 protected String getDocletVersion()
3751 if (null == docletVersion) {
3752 docletVersion = gnu.classpath.Configuration.CLASSPATH_VERSION;
3754 return docletVersion;
3757 private Map getStylesheets()
3759 Map sheets = new HashMap();
3760 if (null != optionStylesheetFile.getValue()) {
3761 sheets.put("User-specified", new String[] {
3762 "resources/user.css"
3766 List cleanSheets = new LinkedList();
3767 cleanSheets.add("resources/gjdochtml-clean-layout.css");
3768 cleanSheets.add("resources/gjdochtml-clean-color1.css");
3769 if (null != optionAddStylesheet.getValue()) {
3770 cleanSheets.add("resources/user.css");
3772 sheets.put("GNU Clean", cleanSheets.toArray(new String[0]));
3777 protected boolean isSinglePackage()
3779 if (getRootDoc().firstSentenceTags().length > 0) {
3782 else if (null != optionDocTitle.getValue()
3783 || null != optionTitle.getValue()) {
3787 return super.isSinglePackage();
3791 private String getTypeParameters(ClassDoc classDoc)
3793 String parameters = "";
3794 TypeVariable[] params = classDoc.typeParameters();
3795 if (params != null && params.length > 0)
3797 parameters = "<";
3798 for (int a = 0; a < params.length; ++a)
3800 parameters += params[a].typeName();
3801 Type[] bounds = params[a].bounds();
3804 parameters += " extends ";
3805 for (int b = 0; a < bounds.length; ++b)
3807 parameters += bounds[a];
3808 if (b != bounds.length - 1)
3809 parameters += " & ";
3812 if (a != params.length - 1)
3815 parameters += ">";
3820 private String transformReferencedMemberName(String referencedMemberName,
3821 boolean javadocCompatibility)
3823 if (!javadocCompatibility) {
3824 StringBuffer result = new StringBuffer();
3825 for (int i=0; i<referencedMemberName.length(); ++i) {
3826 char c = referencedMemberName.charAt(i);
3828 case '(': result.append(':'); break;
3830 case ',': result.append(':'); break;
3831 case '[': result.append('-'); break;
3833 default: result.append(c); break;
3836 return result.toString();
3839 return referencedMemberName;
3843 public void writeGjdocProperties(File outputFile)
3846 Properties properties = new Properties();
3847 properties.setProperty("gjdoc.version", getDocletVersion());
3848 properties.setProperty("gjdoc.compat", Boolean.toString(isJavadocCompatibleNames()));
3850 FileOutputStream out = new FileOutputStream(outputFile);
3851 properties.store(out, "GNU Gjdoc API Documentation Set Descriptor");
3855 public boolean isJavadocCompatibleNames()
3857 return !optionValidHtml.getValue();
3860 private HtmlPage newHtmlPage(File file,
3864 return new HtmlPage(file,
3866 getOutputDocEncoding(),
3867 optionBaseUrl.getValue(),
3868 getTargetDirectory());
3871 private HtmlPage newHtmlPage(File file,
3876 return new HtmlPage(file,
3878 getOutputDocEncoding(),
3879 optionBaseUrl.getValue(),
3880 getTargetDirectory(),