1 /* gnu.classpath.tools.doclets.htmldoclet.HtmlDoclet
2 Copyright (C) 2004 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 package gnu.classpath.tools.doclets.htmldoclet;
23 import gnu.classpath.tools.IOToolkit;
25 import gnu.classpath.tools.doclets.AbstractDoclet;
26 import gnu.classpath.tools.doclets.DocletConfigurationException;
27 import gnu.classpath.tools.doclets.DocletOption;
28 import gnu.classpath.tools.doclets.DocletOptionFile;
29 import gnu.classpath.tools.doclets.DocletOptionFlag;
30 import gnu.classpath.tools.doclets.DocletOptionString;
31 import gnu.classpath.tools.doclets.PackageGroup;
32 import gnu.classpath.tools.doclets.TagletPrinter;
33 import gnu.classpath.tools.doclets.InlineTagRenderer;
35 import gnu.classpath.tools.doclets.xmldoclet.HtmlRepairer;
37 import gnu.classpath.tools.taglets.GnuExtendedTaglet;
38 import gnu.classpath.tools.taglets.TagletContext;
40 import gnu.classpath.tools.java2xhtml.Java2xhtml;
42 import gnu.classpath.tools.StringToolkit;
44 import com.sun.javadoc.*;
45 import com.sun.tools.doclets.Taglet;
47 import java.io.ByteArrayInputStream;
49 import java.io.FileInputStream;
50 import java.io.FileNotFoundException;
51 import java.io.FileOutputStream;
52 import java.io.FileReader;
53 import java.io.FileWriter;
54 import java.io.InputStream;
55 import java.io.InputStreamReader;
56 import java.io.IOException;
57 import java.io.OutputStreamWriter;
58 import java.io.PrintWriter;
59 import java.io.StringWriter;
61 import java.net.MalformedURLException;
63 import java.nio.charset.Charset;
65 import java.text.DateFormat;
66 import java.text.MessageFormat;
68 import java.util.Arrays;
69 import java.util.Calendar;
70 import java.util.Collection;
71 import java.util.Date;
72 import java.util.HashMap;
73 import java.util.Iterator;
74 import java.util.LinkedHashSet;
75 import java.util.LinkedList;
76 import java.util.List;
77 import java.util.ListIterator;
78 import java.util.Locale;
80 import java.util.Properties;
82 import java.util.SortedSet;
83 import java.util.TimeZone;
84 import java.util.TreeSet;
86 public class HtmlDoclet
87 extends AbstractDoclet
88 implements InlineTagRenderer
90 private static String filenameExtension = ".html";
93 * Contains ExternalDocSet.
95 private List externalDocSets = new LinkedList();
98 * Contains String->ExternalDocSet.
100 private Map packageNameToDocSet = new HashMap();
103 * Cache for version string from resource /version.properties
105 private String docletVersion;
108 * For now, do not output a help page.
110 private static final boolean outputHelpPage = false;
113 * Stores the output encoding (either the one specified using
114 * -charset, or the platform default encoding).
116 private String outputCharset;
118 private void printNavBar(HtmlPage output, String currentPage, ClassDoc currentClass)
120 output.beginDiv(CssClass.NAVBAR_TOP);
122 boolean overviewLevel
123 = ("overview".equals(currentPage)
124 || "full-tree".equals(currentPage)
125 || "index".equals(currentPage)
126 || "split-index".equals(currentPage)
127 || "serialized".equals(currentPage)
128 || "deprecated".equals(currentPage)
129 || "about".equals(currentPage)
132 if (!isSinglePackage()) {
133 if ("overview".equals(currentPage)) {
134 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
135 output.print("Overview");
136 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
139 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
140 output.beginAnchor(output.getPathToRoot() + "/overview-summary" + filenameExtension);
141 output.print("Overview");
143 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
149 if (!overviewLevel || isSinglePackage()) {
150 if ("package".equals(currentPage)) {
151 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
152 output.print("Package");
153 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
156 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
158 if (isSinglePackage()) {
159 packageHref = output.getPathToRoot() + "/" + getPackageURL(getSinglePackage()) + "package-summary" + filenameExtension;
162 packageHref = "package-summary" + filenameExtension;
164 output.beginAnchor(packageHref);
165 output.print("Package");
167 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
171 output.beginSpan(CssClass.NAVBAR_ITEM_DISABLED);
172 output.print("Package");
173 output.endSpan(CssClass.NAVBAR_ITEM_DISABLED);
176 if (optionUse.getValue() || optionLinkSource.getValue()) {
179 if (null != currentClass) {
180 if ("class".equals(currentPage)) {
181 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
182 output.print("Class");
183 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
186 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
187 output.beginAnchor(currentClass.name() + filenameExtension);
188 output.print("Class");
190 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
194 output.beginSpan(CssClass.NAVBAR_ITEM_DISABLED);
195 output.print("Class");
196 output.endSpan(CssClass.NAVBAR_ITEM_DISABLED);
199 if (optionUse.getValue()) {
202 if (null != currentClass) {
203 if ("uses".equals(currentPage)) {
204 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
206 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
209 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
210 output.beginAnchor(currentClass.name() + "-uses" + filenameExtension);
213 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
217 output.beginSpan(CssClass.NAVBAR_ITEM_DISABLED);
219 output.endSpan(CssClass.NAVBAR_ITEM_DISABLED);
223 if (optionLinkSource.getValue()) {
227 if ("source".equals(currentPage)) {
228 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
229 output.print("Source");
230 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
234 if (null != currentClass) {
236 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
237 String targetClassName = currentClass.name();
238 String targetAnchor = "";
239 if (null != currentClass.containingClass()) {
240 targetClassName = getOuterClassDoc(currentClass).name();
241 targetAnchor = "#line." + currentClass.position().line();
243 output.beginAnchor(targetClassName + "-source" + filenameExtension + targetAnchor);
244 output.print("Source");
246 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
249 output.beginSpan(CssClass.NAVBAR_ITEM_DISABLED);
250 output.print("Source");
251 output.endSpan(CssClass.NAVBAR_ITEM_DISABLED);
258 if (!optionNoTree.getValue()) {
261 if ("full-tree".equals(currentPage)
262 || "package-tree".equals(currentPage)) {
263 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
264 output.print("Tree");
265 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
268 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
270 if (isSinglePackage() && overviewLevel) {
271 treeHref = getPackageURL(getSinglePackage()) + "tree" + filenameExtension;
274 treeHref = "tree" + filenameExtension;
277 output.beginAnchor(treeHref);
278 output.print("Tree");
280 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
287 if (optionSplitIndex.getValue()) {
288 indexName = "alphaindex-1";
291 indexName = "alphaindex";
294 if ("index".equals(currentPage) || "split-index".equals(currentPage)) {
295 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
296 output.print("Index");
297 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
300 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
301 output.beginAnchor(output.getPathToRoot() + "/" + indexName + filenameExtension);
302 output.print("Index");
304 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
307 if (!optionNoDeprecatedList.getValue()) {
310 if ("deprecated".equals(currentPage)) {
311 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
312 output.print("Deprecated");
313 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
316 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
317 output.beginAnchor(output.getPathToRoot() + "/deprecated" + filenameExtension);
318 output.print("Deprecated");
320 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
324 if (outputHelpPage) {
325 if (!optionNoHelp.getValue()) {
328 if ("help".equals(currentPage)) {
329 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
330 output.print("Help");
331 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
334 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
335 output.beginAnchor(output.getPathToRoot() + "/help" + filenameExtension);
336 output.print("Help");
338 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
345 if ("about".equals(currentPage)) {
346 output.beginSpan(CssClass.NAVBAR_ITEM_ACTIVE);
347 output.print("About");
348 output.endSpan(CssClass.NAVBAR_ITEM_ACTIVE);
351 output.beginSpan(CssClass.NAVBAR_ITEM_ENABLED);
352 output.beginAnchor(output.getPathToRoot() + "/about" + filenameExtension);
353 output.print("About");
355 output.endSpan(CssClass.NAVBAR_ITEM_ENABLED);
358 output.endDiv(CssClass.NAVBAR_TOP);
361 private void printNavBarTopRow(HtmlPage output, String currentPage, ClassDoc currentClass)
364 output.beginCell(CssClass.NAVBAR_TOP);
365 printNavBar(output, currentPage, currentClass);
367 if (null != optionHeader.getValue()) {
368 output.beginCell(CssClass.NAVBAR_TOP_HEADER);
369 output.print(replaceDocRoot(output, optionHeader.getValue()));
375 private void printNavBarTopNaviCell(HtmlPage output)
377 output.beginCell(CssClass.NAVBAR_TOP_NAVI);
378 output.beginAnchor(output.getPathToRoot() + "/index" + filenameExtension, "Show in a frameset", "_top");
379 output.print("Frames");
383 output.beginAnchor(output.getFile().getName(), "Show without frames", "_top");
384 output.print("No Frames");
391 private void printNavBarTop(HtmlPage output, String currentPage)
393 printNavBarTop(output, currentPage, null, null, null);
396 private void printNavBarTop(HtmlPage output, String currentPage,
397 ClassDoc currentClass, Object prev, Object next)
399 if (!optionNoNavBar.getValue()) {
400 output.beginTable(CssClass.NAVBAR_TOP);
401 printNavBarTopRow(output, currentPage, currentClass);
403 if ("class".equals(currentPage)) {
404 output.beginCell(CssClass.NAVBAR_TOP_NAVI);
405 ClassDoc prevClass = (ClassDoc)prev;
406 ClassDoc nextClass = (ClassDoc)next;
407 if (null != prevClass) {
408 output.anchor(getClassDocURL(output, prevClass), "Prev Class");
411 output.print("Prev Class");
414 if (null != nextClass) {
415 output.anchor(getClassDocURL(output, nextClass), "Next Class");
418 output.print("Next Class");
422 else if ("split-index".equals(currentPage)) {
423 output.beginCell(CssClass.NAVBAR_TOP_NAVI);
424 Integer prevLetter = (Integer)prev;
425 Integer nextLetter = (Integer)next;
426 if (null != prevLetter) {
427 output.anchor("alphaindex-" + prevLetter + filenameExtension, "Prev Letter");
430 output.print("Prev Letter");
433 if (null != nextLetter) {
434 output.anchor("alphaindex-" + nextLetter + filenameExtension, "Next Letter");
437 output.print("Next Letter");
442 output.beginCell(CssClass.NAVBAR_TOP_NAVI);
446 printNavBarTopNaviCell(output);
449 if ("class".equals(currentPage)) {
452 output.beginCell(CssClass.NAVBAR_TOP_NAVI);
453 output.print("Summary: ");
455 if (currentClass.innerClasses().length > 0) {
456 output.anchor("#summary-inner", "Nested");
459 output.print("Nested");
464 if (currentClass.fields().length > 0) {
465 output.anchor("#summary-fields", "Field");
468 output.print("Field");
473 if (currentClass.methods().length > 0) {
474 output.anchor("#summary-methods", "Method");
477 output.print("Method");
482 if (currentClass.constructors().length > 0) {
483 output.anchor("#summary-constructors", "Constr");
486 output.print("Constr");
491 output.beginCell(CssClass.NAVBAR_TOP_NAVI);
492 output.print("Detail: ");
494 if (currentClass.innerClasses().length > 0) {
495 output.anchor("#detail-inner", "Nested");
498 output.print("Nested");
503 if (currentClass.fields().length > 0) {
504 output.anchor("#detail-fields", "Field");
507 output.print("Field");
512 if (currentClass.methods().length > 0) {
513 output.anchor("#detail-methods", "Method");
516 output.print("Method");
521 if (currentClass.constructors().length > 0) {
522 output.anchor("#detail-constructors", "Constr");
525 output.print("Constr");
535 private void printNavBarTopPackage(HtmlPage output, String currentPage,
536 PackageDoc prevPackage, PackageDoc nextPackage)
538 if (!optionNoNavBar.getValue()) {
539 output.beginTable(CssClass.NAVBAR_TOP);
540 printNavBarTopRow(output, currentPage, null);
543 output.beginCell(CssClass.NAVBAR_TOP_NAVI);
544 if (null != prevPackage) {
545 output.anchor(output.getPathToRoot() + "/" + getPackageURL(prevPackage) + "package-summary" + filenameExtension, "Prev Package");
548 output.print("Prev Package");
551 if (null != nextPackage) {
552 output.anchor(output.getPathToRoot() + "/" + getPackageURL(nextPackage) + "package-summary" + filenameExtension, "Next Package");
555 output.print("Next Package");
559 printNavBarTopNaviCell(output);
566 private void printNavBarBottom(HtmlPage output, String currentPage)
568 printNavBarBottom(output, currentPage, null);
571 private void printNavBarBottom(HtmlPage output, String currentPage, ClassDoc currentClass)
573 if ("class".equals(currentPage)) {
574 String boilerplate = null;
575 Tag[] boilerplateTags = getOuterClassDoc(currentClass).tags("@boilerplate");
576 if (boilerplateTags.length > 0) {
577 boilerplate = boilerplateTags[0].text();
579 if (null != boilerplate) {
581 output.beginDiv(CssClass.CLASS_BOILERPLATE);
582 output.print(boilerplate);
583 output.endDiv(CssClass.CLASS_BOILERPLATE);
588 if (!optionNoNavBar.getValue()) {
589 output.beginDiv(CssClass.NAVBAR_BOTTOM_SPACER);
591 output.endDiv(CssClass.NAVBAR_BOTTOM_SPACER);
592 output.beginTable(CssClass.NAVBAR_BOTTOM);
595 printNavBar(output, currentPage, currentClass);
597 if (null != optionFooter.getValue()) {
599 output.print(replaceDocRoot(output, optionFooter.getValue()));
606 if (null != optionBottom.getValue()) {
608 output.print(replaceDocRoot(output, optionBottom.getValue()));
612 private void printPackagePageClasses(HtmlPage output, ClassDoc[] classDocs, String header)
614 if (classDocs.length > 0) {
615 output.beginDiv(CssClass.TABLE_CONTAINER);
616 output.beginTable(CssClass.PACKAGE_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
617 output.rowDiv(CssClass.TABLE_HEADER, header);
619 for (int i=0; i<classDocs.length; ++i) {
620 ClassDoc classDoc = classDocs[i];
621 if (classDoc.isIncluded()) {
624 output.beginCell(CssClass.PACKAGE_SUMMARY_LEFT);
625 printType(output, classDoc);
628 output.beginCell(CssClass.PACKAGE_SUMMARY_RIGHT);
629 printTags(output, classDoc, classDoc.firstSentenceTags(), true);
635 output.endDiv(CssClass.TABLE_CONTAINER);
640 private void printPackagesListFile()
644 = new PrintWriter(new OutputStreamWriter(new FileOutputStream(new File(getTargetDirectory(),
648 PackageDoc[] packages = getRootDoc().specifiedPackages();
649 for (int i=0; i<packages.length; ++i) {
650 String packageName = packages[i].name();
651 if (packageName.length() > 0) {
652 out.println(packageName);
659 private void printPackagePage(File packageDir, String pathToRoot,
660 PackageDoc packageDoc,
661 PackageDoc prevPackageDoc,
662 PackageDoc nextPackageDoc)
665 HtmlPage output = newHtmlPage(new File(packageDir, "package-summary" + filenameExtension),
668 Set keywords = new LinkedHashSet();
669 keywords.add(packageDoc.name() + " packages");
671 output.beginPage(getPageTitle(packageDoc.name()), getOutputCharset(),
672 keywords, getStylesheets());
673 output.beginBody(CssClass.BODY_CONTENT_PACKAGE);
674 printNavBarTopPackage(output, "package", prevPackageDoc, nextPackageDoc);
676 output.beginDiv(CssClass.PACKAGE_TITLE);
677 output.print("Package ");
678 if (packageDoc.name().length() > 0) {
679 output.print(packageDoc.name());
682 output.print("<Unnamed>");
684 output.endDiv(CssClass.PACKAGE_TITLE);
686 output.beginDiv(CssClass.PACKAGE_DESCRIPTION_TOP);
687 printTags(output, packageDoc, packageDoc.firstSentenceTags(), true);
688 output.endDiv(CssClass.PACKAGE_DESCRIPTION_TOP);
690 printPackagePageClasses(output, packageDoc.interfaces(),
691 "Interface Summary");
692 printPackagePageClasses(output, packageDoc.ordinaryClasses(),
694 printPackagePageClasses(output, packageDoc.exceptions(),
695 "Exception Summary");
696 printPackagePageClasses(output, packageDoc.errors(),
699 output.anchorName("description");
700 output.beginDiv(CssClass.PACKAGE_DESCRIPTION_FULL);
701 printTags(output, packageDoc, packageDoc.inlineTags(), false);
702 output.endDiv(CssClass.PACKAGE_DESCRIPTION_FULL);
704 printNavBarBottom(output, "package");
710 static class TreeNode
711 implements Comparable
714 SortedSet children = new TreeSet();
716 TreeNode(ClassDoc classDoc) {
717 TreeNode.this.classDoc = classDoc;
720 public boolean equals(Object other)
722 return classDoc.equals(((TreeNode)other).classDoc);
725 public int compareTo(Object other)
727 return classDoc.compareTo(((TreeNode)other).classDoc);
730 public int hashCode()
732 return classDoc.hashCode();
736 private TreeNode addClassTreeNode(Map treeMap, ClassDoc classDoc)
738 TreeNode node = (TreeNode)treeMap.get(classDoc.qualifiedName());
740 node = new TreeNode(classDoc);
741 treeMap.put(classDoc.qualifiedName(), node);
743 ClassDoc superClassDoc = (ClassDoc)classDoc.superclass();
744 if (null != superClassDoc) {
745 TreeNode parentNode = addClassTreeNode(treeMap, superClassDoc);
746 parentNode.children.add(node);
752 private TreeNode addInterfaceTreeNode(Map treeMap, ClassDoc classDoc)
754 TreeNode node = (TreeNode)treeMap.get(classDoc.qualifiedName());
756 node = new TreeNode(classDoc);
757 treeMap.put(classDoc.qualifiedName(), node);
759 ClassDoc[] superInterfaces = classDoc.interfaces();
760 if (null != superInterfaces && superInterfaces.length > 0) {
761 for (int i=0; i<superInterfaces.length; ++i) {
762 TreeNode parentNode = addInterfaceTreeNode(treeMap, superInterfaces[i]);
763 parentNode.children.add(node);
767 TreeNode rootNode = (TreeNode)treeMap.get("<root>");
768 if (null == rootNode) {
769 rootNode = new TreeNode(null);
770 treeMap.put("<root>", rootNode);
772 rootNode.children.add(node);
778 private void printPackageTreeRec(HtmlPage output, TreeNode node, TreeNode parentNode)
780 output.beginElement("li", "class", "node");
781 output.beginElement("div");
782 if (node.classDoc.isIncluded()) {
783 String packageName = node.classDoc.containingPackage().name();
784 if (packageName.length() > 0) {
785 output.print(packageName);
788 output.beginSpan(CssClass.TREE_LINK);
789 printType(output, node.classDoc);
790 output.endSpan(CssClass.TREE_LINK);
793 output.print(possiblyQualifiedName(node.classDoc));
795 ClassDoc[] interfaces = node.classDoc.interfaces();
796 ClassDoc parentClassDoc = null;
797 if (null != parentNode) {
798 parentClassDoc = parentNode.classDoc;
800 if (interfaces.length > 0
801 && !(interfaces.length == 1 && interfaces[0].equals(parentClassDoc))) {
802 if (node.classDoc.isInterface()) {
803 output.print(" (also implements ");
806 output.print(" (implements ");
809 boolean firstItem = true;
810 for (int i=0; i<interfaces.length; ++i) {
811 ClassDoc implemented = interfaces[i];
812 if (!implemented.equals(parentClassDoc)) {
817 if (implemented.isIncluded()) {
818 output.print(implemented.containingPackage().name());
820 printType(output, implemented);
823 output.print(possiblyQualifiedName(implemented));
830 output.endElement("div");
831 output.endElement("li");
832 if (!node.children.isEmpty()) {
833 output.beginElement("li", "class", "level");
834 output.beginElement("ul");
835 Iterator it = node.children.iterator();
836 while (it.hasNext()) {
837 TreeNode child = (TreeNode)it.next();
838 printPackageTreeRec(output, child, node);
840 output.endElement("ul");
841 output.endElement("li");
845 private void printClassTree(HtmlPage output, ClassDoc[] classDocs)
847 Map classTreeMap = new HashMap();
849 for (int i=0; i<classDocs.length; ++i) {
850 ClassDoc classDoc = classDocs[i];
851 if (!classDoc.isInterface()) {
852 addClassTreeNode(classTreeMap, classDoc);
856 TreeNode root = (TreeNode)classTreeMap.get("java.lang.Object");
858 output.div(CssClass.PACKAGE_TREE_SECTION_TITLE, "Class Hierarchy");
859 output.beginDiv(CssClass.PACKAGE_TREE);
860 printPackageTreeRec(output, root, null);
861 output.endDiv(CssClass.PACKAGE_TREE);
865 private void printInterfaceTree(HtmlPage output, ClassDoc[] classDocs)
867 Map interfaceTreeMap = new HashMap();
869 for (int i=0; i<classDocs.length; ++i) {
870 ClassDoc classDoc = classDocs[i];
871 if (classDoc.isInterface()) {
872 addInterfaceTreeNode(interfaceTreeMap, classDoc);
876 TreeNode interfaceRoot = (TreeNode)interfaceTreeMap.get("<root>");
877 if (null != interfaceRoot) {
878 Iterator it = interfaceRoot.children.iterator();
880 output.div(CssClass.PACKAGE_TREE_SECTION_TITLE, "Interface Hierarchy");
881 output.beginDiv(CssClass.PACKAGE_TREE);
882 while (it.hasNext()) {
883 TreeNode node = (TreeNode)it.next();
884 printPackageTreeRec(output, node, null);
886 output.endDiv(CssClass.PACKAGE_TREE);
892 private void printPackageTreePage(File packageDir, String pathToRoot, PackageDoc packageDoc)
895 HtmlPage output = newHtmlPage(new File(packageDir,
896 "tree" + filenameExtension),
898 output.beginPage(getPageTitle(packageDoc.name() + " Hierarchy"),
901 output.beginBody(CssClass.BODY_CONTENT_PACKAGE_TREE);
902 printNavBarTop(output, "package-tree");
904 output.div(CssClass.PACKAGE_TREE_TITLE, "Hierarchy for Package " + packageDoc.name());
906 ClassDoc[] classDocs = packageDoc.allClasses();
907 printClassTree(output, classDocs);
908 printInterfaceTree(output, classDocs);
910 printNavBarBottom(output, "package-tree");
916 private void printFullTreePage()
919 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
920 "tree" + filenameExtension),
922 output.beginPage(getPageTitle("Hierarchy"),
925 output.beginBody(CssClass.BODY_CONTENT_FULL_TREE);
926 printNavBarTop(output, "full-tree");
928 output.div(CssClass.PACKAGE_TREE_TITLE, "Hierarchy for All Packages");
930 output.beginDiv(CssClass.FULL_TREE_PACKAGELIST);
931 output.div(CssClass.FULL_TREE_PACKAGELIST_HEADER, "Package Hierarchies:");
932 output.beginDiv(CssClass.FULL_TREE_PACKAGELIST_ITEM);
933 Set allPackages = getAllPackages();
934 Iterator it = allPackages.iterator();
935 while (it.hasNext()) {
936 PackageDoc packageDoc = (PackageDoc)it.next();
937 output.beginAnchor(getPackageURL(packageDoc) + "tree" + filenameExtension);
938 output.print(packageDoc.name());
944 output.endDiv(CssClass.FULL_TREE_PACKAGELIST_ITEM);
945 output.endDiv(CssClass.FULL_TREE_PACKAGELIST);
947 ClassDoc[] classDocs = getRootDoc().classes();
948 printClassTree(output, classDocs);
949 printInterfaceTree(output, classDocs);
951 printNavBarBottom(output, "full-tree");
957 private void printIndexEntry(HtmlPage output, Doc entry)
959 output.beginDiv(CssClass.INDEX_ENTRY);
960 output.beginDiv(CssClass.INDEX_ENTRY_KEY);
961 String anchor = null;
962 String description = null;
963 if (entry instanceof PackageDoc) {
964 output.beginAnchor(getPackageURL((PackageDoc)entry) + "package-summary" + filenameExtension);
965 output.print(entry.name());
967 output.print(" - package");
969 else if (entry instanceof ClassDoc) {
970 ClassDoc classDoc = (ClassDoc)entry;
971 output.beginAnchor(getClassURL(classDoc));
972 output.print(entry.name() + getTypeParameters(classDoc));
975 if (entry.isInterface()) {
976 output.print("interface ");
978 else if (entry.isException()) {
979 output.print("exception ");
981 else if (entry.isError()) {
982 output.print("error ");
985 output.print("class ");
987 String packageName = classDoc.containingPackage().name();
988 if (packageName.length() > 0) {
989 output.print(packageName);
992 printType(output, classDoc);
995 ProgramElementDoc memberDoc = (ProgramElementDoc)entry;
996 output.beginAnchor(getMemberDocURL(output, memberDoc));
997 output.print(entry.name());
998 if (memberDoc instanceof ExecutableMemberDoc) {
999 output.print(((ExecutableMemberDoc)memberDoc).signature());
1002 output.print(" - ");
1004 if (memberDoc.isStatic()) {
1005 output.print("static ");
1008 if (entry.isConstructor()) {
1009 output.print("constructor for class ");
1011 else if (entry.isMethod()) {
1012 output.print("method in class ");
1014 else if (entry.isField()) {
1015 output.print("field in class ");
1017 ClassDoc containingClass = memberDoc.containingClass();
1018 String packageName = containingClass.containingPackage().name();
1019 if (packageName.length() > 0) {
1020 output.print(packageName);
1023 printType(output, containingClass);
1025 output.endDiv(CssClass.INDEX_ENTRY_KEY);
1026 output.beginDiv(CssClass.INDEX_ENTRY_DESCRIPTION);
1027 printTags(output, entry, entry.firstSentenceTags(), true);
1028 output.endDiv(CssClass.INDEX_ENTRY_DESCRIPTION);
1029 output.endDiv(CssClass.INDEX_ENTRY);
1032 private void printFrameSetPage()
1035 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1036 "index" + filenameExtension),
1038 HtmlPage.DOCTYPE_FRAMESET);
1040 String title = getWindowTitle();
1041 output.beginPage(title, getOutputCharset(), getStylesheets());
1042 output.beginElement("frameset", "cols", "20%,80%");
1045 if (isSinglePackage()) {
1046 output.atomicElement("frame",
1047 new String[] { "src", "name" },
1048 new String[] { getPackageURL(getSinglePackage()) + "classes" + filenameExtension, "classes" });
1049 contentURL = getPackageURL(getSinglePackage()) + "package-summary.html";
1052 output.beginElement("frameset", "rows", "25%,75%");
1053 output.atomicElement("frame",
1054 new String[] { "src", "name" },
1055 new String[] { "all-packages" + filenameExtension, "packages" });
1056 output.atomicElement("frame",
1057 new String[] { "src", "name" },
1058 new String[] { "all-classes" + filenameExtension, "classes" });
1059 output.endElement("frameset");
1060 contentURL = "overview-summary" + filenameExtension;
1062 output.atomicElement("frame",
1063 new String[] { "src", "name" },
1064 new String[] { contentURL, "content" });
1065 output.endElement("frameset");
1070 private void printPackagesMenuPage()
1073 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1074 "all-packages" + filenameExtension),
1076 output.beginPage(getPageTitle("Package Menu"), getOutputCharset(), getStylesheets());
1077 output.beginBody(CssClass.BODY_MENU_PACKAGES, false);
1079 output.beginSpan(CssClass.PACKAGE_MENU_ENTRY);
1080 output.beginAnchor("all-classes" + filenameExtension,
1083 output.print("All Classes");
1085 output.endSpan(CssClass.PACKAGE_MENU_ENTRY);
1087 output.div(CssClass.PACKAGE_MENU_TITLE, "Packages");
1089 output.beginDiv(CssClass.PACKAGE_MENU_LIST);
1091 Set packageDocs = getAllPackages();
1092 Iterator it = packageDocs.iterator();
1093 while (it.hasNext()) {
1094 PackageDoc packageDoc = (PackageDoc)it.next();
1095 output.beginSpan(CssClass.PACKAGE_MENU_ENTRY);
1096 output.beginAnchor(getPackageURL(packageDoc) + "classes" + filenameExtension,
1099 if (packageDoc.name().length() > 0) {
1100 output.print(packageDoc.name());
1103 output.print("<unnamed package>");
1106 output.endSpan(CssClass.PACKAGE_MENU_ENTRY);
1110 output.endDiv(CssClass.PACKAGE_MENU_LIST);
1116 private void printClassMenuEntry(HtmlPage output, ClassDoc classDoc)
1118 CssClass entryClass;
1119 if (classDoc.isInterface()) {
1120 entryClass = CssClass.CLASS_MENU_ENTRY_INTERFACE;
1123 entryClass = CssClass.CLASS_MENU_ENTRY_CLASS;
1125 output.beginSpan(entryClass);
1126 output.beginAnchor(getClassDocURL(output, classDoc),
1127 classDoc.qualifiedTypeName(),
1129 output.print(classDoc.name());
1131 output.endSpan(entryClass);
1135 private void printClassMenuSection(HtmlPage output, Collection classDocs, String header)
1137 if (!classDocs.isEmpty()) {
1138 output.div(CssClass.CLASS_MENU_SUBTITLE, header);
1139 Iterator it = classDocs.iterator();
1140 while (it.hasNext()) {
1141 ClassDoc classDoc = (ClassDoc)it.next();
1142 printClassMenuEntry(output, classDoc);
1147 private void printClassMenuList(HtmlPage output, ClassDoc[] classDocs, boolean categorized)
1149 output.beginDiv(CssClass.CLASS_MENU_LIST);
1152 Set classes = new TreeSet();
1153 Set interfaces = new TreeSet();
1154 Set exceptions = new TreeSet();
1155 Set errors = new TreeSet();
1157 for (int i=0; i<classDocs.length; ++i) {
1158 ClassDoc classDoc = classDocs[i];
1159 if (classDoc.isInterface()) {
1160 interfaces.add(classDoc);
1162 else if (classDoc.isException()) {
1163 exceptions.add(classDoc);
1165 else if (classDoc.isError()) {
1166 errors.add(classDoc);
1169 classes.add(classDoc);
1172 printClassMenuSection(output, interfaces, "Interfaces");
1173 printClassMenuSection(output, classes, "Classes");
1174 printClassMenuSection(output, exceptions, "Exceptions");
1175 printClassMenuSection(output, errors, "Errors");
1178 for (int i=0; i<classDocs.length; ++i) {
1179 ClassDoc classDoc = classDocs[i];
1180 if (classDoc.isIncluded()) {
1181 printClassMenuEntry(output, classDoc);
1186 output.endDiv(CssClass.CLASS_MENU_LIST);
1189 private void printAllClassesMenuPage()
1192 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1193 "all-classes" + filenameExtension),
1195 output.beginPage(getPageTitle("Class Menu"), getOutputCharset(), getStylesheets());
1196 output.beginBody(CssClass.BODY_MENU_CLASSES, false);
1198 output.div(CssClass.CLASS_MENU_TITLE, "All Classes");
1200 printClassMenuList(output, getRootDoc().classes(), false);
1207 private void printPackageClassesMenuPage(File packageDir, String pathToRoot, PackageDoc packageDoc)
1210 HtmlPage output = newHtmlPage(new File(packageDir,
1211 "classes" + filenameExtension),
1214 output.beginPage(getPageTitle(packageDoc.name() + " Class Menu"),
1215 getOutputCharset(), getStylesheets());
1216 output.beginBody(CssClass.BODY_MENU_CLASSES, false);
1218 output.beginDiv(CssClass.CLASS_MENU_TITLE);
1219 output.beginAnchor("package-summary" + filenameExtension, "", "content");
1220 if (packageDoc.name().length() > 0) {
1221 output.print(packageDoc.name());
1224 output.print("<Unnamed>");
1227 output.endDiv(CssClass.CLASS_MENU_TITLE);
1229 printClassMenuList(output, packageDoc.allClasses(), true);
1236 private void printSplitIndex()
1239 Map categorizedIndex = getCategorizedIndex();
1240 Iterator it = categorizedIndex.keySet().iterator();
1242 int count = categorizedIndex.size();
1243 while (it.hasNext()) {
1244 Character c = (Character)it.next();
1245 List classList = (List)categorizedIndex.get(c);
1246 printIndexPage(n++, count, c, classList);
1250 private void printIndexPage()
1253 printIndexPage(0, 0, null, null);
1256 private void printIndexPage(int index, int maxIndex, Character letter, List classList)
1259 String pageName = "alphaindex";
1260 if (null != letter) {
1261 pageName += "-" + index;
1263 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1264 pageName + filenameExtension),
1266 output.beginPage(getPageTitle("Alphabetical Index"),
1269 output.beginBody(CssClass.BODY_CONTENT_INDEX);
1270 if (null == letter) {
1271 printNavBarTop(output, "index");
1274 printNavBarTop(output, "split-index", null,
1275 (index > 1) ? new Integer(index - 1) : null,
1276 (index < maxIndex) ? new Integer(index + 1) : null);
1281 if (null == letter) {
1282 title = "Alphabetical Index";
1285 title = "Alphabetical Index: " + letter;
1287 output.div(CssClass.INDEX_TITLE, title);
1289 if (null != letter || getCategorizedIndex().keySet().size() > 1) {
1290 output.beginDiv(CssClass.INDEX_LETTERS);
1292 Iterator it = getCategorizedIndex().keySet().iterator();
1294 while (it.hasNext()) {
1295 Character c = (Character)it.next();
1296 output.beginSpan(CssClass.INDEX_LETTER);
1297 if (letter != null) {
1298 output.beginAnchor("alphaindex-" + n + filenameExtension);
1301 output.beginAnchor("#" + c);
1303 output.print(c.toString());
1305 output.endSpan(CssClass.INDEX_LETTER);
1306 output.beginSpan(CssClass.INDEX_LETTER_SPACER);
1308 output.endSpan(CssClass.INDEX_LETTER_SPACER);
1313 output.endDiv(CssClass.INDEX_LETTERS);
1316 if (null != letter) {
1317 printIndexCategory(output, letter, classList);
1320 Map categorizedIndex = getCategorizedIndex();
1321 Iterator categoryIt = categorizedIndex.keySet().iterator();
1323 while (categoryIt.hasNext()) {
1324 letter = (Character)categoryIt.next();
1325 classList = (List)categorizedIndex.get(letter);
1326 output.anchorName(letter.toString());
1327 printIndexCategory(output, letter, classList);
1331 printNavBarBottom(output, "index");
1337 private void printIndexCategory(HtmlPage output, Character letter, List classList)
1339 Iterator it = classList.iterator();
1341 output.div(CssClass.INDEX_CATEGORY_HEADER, letter.toString());
1342 output.beginDiv(CssClass.INDEX_CATEGORY);
1343 while (it.hasNext()) {
1344 Doc entry = (Doc)it.next();
1345 printIndexEntry(output, entry);
1347 output.endDiv(CssClass.INDEX_CATEGORY);
1350 private void printDeprecationSummary(HtmlPage output, List docs, String header)
1352 if (!docs.isEmpty()) {
1353 output.beginDiv(CssClass.TABLE_CONTAINER);
1354 output.beginTable(CssClass.DEPRECATION_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
1355 output.rowDiv(CssClass.TABLE_HEADER, header);
1357 Iterator it = docs.iterator();
1358 while (it.hasNext()) {
1359 Doc doc = (Doc)it.next();
1362 output.beginCell(CssClass.DEPRECATION_SUMMARY_LEFT);
1363 if (doc instanceof Type) {
1364 printType(output, (Type)doc);
1367 ProgramElementDoc memberDoc = (ProgramElementDoc)doc;
1368 output.beginAnchor(getMemberDocURL(output, memberDoc));
1369 output.print(memberDoc.containingClass().qualifiedName());
1371 output.print(memberDoc.name());
1372 if (memberDoc instanceof ExecutableMemberDoc) {
1373 output.print(((ExecutableMemberDoc)memberDoc).flatSignature());
1377 output.beginDiv(CssClass.DEPRECATION_SUMMARY_DESCRIPTION);
1378 printTags(output, doc, doc.tags("deprecated")[0].firstSentenceTags(), true);
1379 output.endDiv(CssClass.DEPRECATION_SUMMARY_DESCRIPTION);
1386 output.endDiv(CssClass.TABLE_CONTAINER);
1392 private void printSerializationPage()
1395 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1396 "serialized-form" + filenameExtension),
1398 output.beginPage(getPageTitle("Serialized Form"),
1401 output.beginBody(CssClass.BODY_CONTENT_DEPRECATED);
1402 printNavBarTop(output, "serialized");
1404 output.div(CssClass.SERIALIZED_TITLE, "Serialized Form");
1406 Iterator it = getAllPackages().iterator();
1408 while (it.hasNext()) {
1410 PackageDoc packageDoc = (PackageDoc)it.next();
1412 List serializableClasses = new LinkedList();
1413 ClassDoc[] classes = packageDoc.allClasses();
1414 for (int i=0; i<classes.length; ++i) {
1415 ClassDoc classDoc = classes[i];
1416 if (classDoc.isSerializable() || classDoc.isExternalizable()) {
1417 serializableClasses.add(classDoc);
1421 if (!serializableClasses.isEmpty()) {
1422 output.div(CssClass.SERIALIZED_PACKAGE_HEADER, "Package " + packageDoc.name());
1424 Iterator cit = serializableClasses.iterator();
1425 while (cit.hasNext()) {
1426 ClassDoc classDoc = (ClassDoc)cit.next();
1428 output.anchorName(classDoc.qualifiedTypeName());
1430 output.beginDiv(CssClass.SERIALIZED_CLASS_HEADER);
1431 output.print("Class ");
1432 printType(output, classDoc, true);
1433 output.print(" extends ");
1434 printType(output, classDoc.superclass());
1435 output.print(" implements Serializable");
1436 output.endDiv(CssClass.SERIALIZED_CLASS_HEADER);
1438 FieldDoc serialVersionUidField = findField(classDoc, "serialVersionUID");
1439 if (null != serialVersionUidField
1440 && serialVersionUidField.isFinal()
1441 && serialVersionUidField.isStatic()
1442 && serialVersionUidField.type().typeName().equals("long")) {
1444 String fieldValue = serialVersionUidField.constantValueExpression();
1445 if (null != fieldValue) {
1446 output.beginDiv(CssClass.SERIALIZED_SVUID_OUTER);
1447 output.span(CssClass.SERIALIZED_SVUID_HEADER, "serialVersionUID: ");
1448 output.span(CssClass.SERIALIZED_SVUID_VALUE, fieldValue);
1449 output.endDiv(CssClass.SERIALIZED_SVUID_OUTER);
1452 printMemberDetails(output,
1453 classDoc.serializationMethods(),
1454 "Serialization Methods",
1456 printMemberDetails(output,
1457 classDoc.serializableFields(),
1458 "Serialized Fields",
1464 printNavBarBottom(output, "serialized");
1472 private void printDeprecationPage()
1475 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1476 "deprecated" + filenameExtension),
1478 output.beginPage(getPageTitle("Deprecated API"),
1481 output.beginBody(CssClass.BODY_CONTENT_DEPRECATED);
1482 printNavBarTop(output, "deprecated");
1484 output.div(CssClass.DEPRECATION_TITLE, "Deprecated API");
1486 List deprecatedInterfaces = new LinkedList();
1487 List deprecatedExceptions = new LinkedList();
1488 List deprecatedErrors = new LinkedList();
1489 List deprecatedClasses = new LinkedList();
1490 List deprecatedFields = new LinkedList();
1491 List deprecatedMethods = new LinkedList();
1492 List deprecatedConstructors = new LinkedList();
1494 ClassDoc[] classDocs = getRootDoc().classes();
1495 for (int i=0; i<classDocs.length; ++i) {
1496 ClassDoc classDoc = classDocs[i];
1498 Tag[] deprecatedTags = classDoc.tags("deprecated");
1499 if (null != deprecatedTags && deprecatedTags.length > 0) {
1500 if (classDoc.isInterface()) {
1501 deprecatedInterfaces.add(classDoc);
1503 else if (classDoc.isException()) {
1504 deprecatedExceptions.add(classDoc);
1506 else if (classDoc.isError()) {
1507 deprecatedErrors.add(classDoc);
1510 deprecatedClasses.add(classDoc);
1514 ConstructorDoc[] constructors = classDoc.constructors();
1515 for (int j=0; j<constructors.length; ++j) {
1516 Tag[] deprecatedTags = constructors[j].tags("deprecated");
1517 if (null != deprecatedTags && deprecatedTags.length > 0) {
1518 deprecatedConstructors.add(constructors[j]);
1521 MethodDoc[] methods = classDoc.methods();
1522 for (int j=0; j<methods.length; ++j) {
1523 Tag[] deprecatedTags = methods[j].tags("deprecated");
1524 if (null != deprecatedTags && deprecatedTags.length > 0) {
1525 deprecatedMethods.add(methods[j]);
1528 FieldDoc[] fields = classDoc.fields();
1529 for (int j=0; j<fields.length; ++j) {
1530 Tag[] deprecatedTags = fields[j].tags("deprecated");
1531 if (null != deprecatedTags && deprecatedTags.length > 0) {
1532 deprecatedFields.add(fields[j]);
1537 if (!deprecatedInterfaces.isEmpty()
1538 || !deprecatedClasses.isEmpty()
1539 || !deprecatedExceptions.isEmpty()
1540 || !deprecatedErrors.isEmpty()
1541 || !deprecatedFields.isEmpty()
1542 || !deprecatedMethods.isEmpty()
1543 || !deprecatedConstructors.isEmpty()) {
1545 output.beginDiv(CssClass.DEPRECATION_TOC);
1546 output.div(CssClass.DEPRECATION_TOC_HEADER, "Contents");
1547 output.beginDiv(CssClass.DEPRECATION_TOC_LIST);
1548 if (!deprecatedInterfaces.isEmpty()) {
1549 output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
1550 output.anchor("#interfaces", "Deprecated Interfaces");
1551 output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
1553 if (!deprecatedClasses.isEmpty()) {
1554 output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
1555 output.anchor("#classes", "Deprecated Classes");
1556 output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
1558 if (!deprecatedExceptions.isEmpty()) {
1559 output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
1560 output.anchor("#exceptions", "Deprecated Exceptions");
1561 output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
1563 if (!deprecatedErrors.isEmpty()) {
1564 output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
1565 output.anchor("#errors", "Deprecated Errors");
1566 output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
1568 if (!deprecatedFields.isEmpty()) {
1569 output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
1570 output.anchor("#fields", "Deprecated Fields");
1571 output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
1573 if (!deprecatedMethods.isEmpty()) {
1574 output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
1575 output.anchor("#methods", "Deprecated Methods");
1576 output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
1578 if (!deprecatedConstructors.isEmpty()) {
1579 output.beginDiv(CssClass.DEPRECATION_TOC_ENTRY);
1580 output.anchor("#constructors", "Deprecated Constructors");
1581 output.endDiv(CssClass.DEPRECATION_TOC_ENTRY);
1583 output.endDiv(CssClass.DEPRECATION_TOC_LIST);
1584 output.endDiv(CssClass.DEPRECATION_TOC);
1585 output.beginDiv(CssClass.DEPRECATION_LIST);
1587 output.anchorName("interfaces");
1588 printDeprecationSummary(output, deprecatedInterfaces, "Deprecated Interfaces");
1590 output.anchorName("classes");
1591 printDeprecationSummary(output, deprecatedClasses, "Deprecated Classes");
1593 output.anchorName("exceptions");
1594 printDeprecationSummary(output, deprecatedExceptions, "Deprecated Exceptions");
1596 output.anchorName("errors");
1597 printDeprecationSummary(output, deprecatedErrors, "Deprecated Errors");
1599 output.anchorName("fields");
1600 printDeprecationSummary(output, deprecatedFields, "Deprecated Fields");
1602 output.anchorName("methods");
1603 printDeprecationSummary(output, deprecatedMethods, "Deprecated Methods");
1605 output.anchorName("constructors");
1606 printDeprecationSummary(output, deprecatedConstructors, "Deprecated Constructors");
1608 output.endDiv(CssClass.DEPRECATION_LIST);
1611 output.beginDiv(CssClass.DEPRECATION_EMPTY);
1612 output.print("No deprecated classes or class members in this API.");
1613 output.endDiv(CssClass.DEPRECATION_EMPTY);
1617 printNavBarBottom(output, "deprecated");
1623 private void printAboutPage()
1626 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1627 "about" + filenameExtension),
1629 output.beginPage(getPageTitle("About"),
1632 output.beginBody(CssClass.BODY_CONTENT_ABOUT);
1634 printNavBarTop(output, "about");
1636 output.div(CssClass.ABOUT_TITLE, "About");
1638 output.beginDiv(CssClass.ABOUT_GENERATOR);
1639 output.print("Generated by ");
1640 output.print("Gjdoc");
1641 output.print(" HtmlDoclet ");
1642 output.print(getDocletVersion());
1643 output.print(", part of ");
1644 output.beginAnchor("http://www.gnu.org/software/classpath/cp-tools/", "", "_top");
1645 output.print("GNU Classpath Tools");
1647 output.print(", on ");
1648 DateFormat format = DateFormat.getDateTimeInstance(DateFormat.LONG,
1651 Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"),
1653 format.setCalendar(cal);
1654 output.print(format.format(new Date()));
1656 output.endDiv(CssClass.ABOUT_GENERATOR);
1658 printNavBarBottom(output, "about");
1665 private void printSourcePage(File packageDir, ClassDoc classDoc, String sourceXhtml)
1668 HtmlPage output = newHtmlPage(new File(packageDir,
1669 classDoc.name() + "-source" + filenameExtension),
1670 getPathToRoot(packageDir, getTargetDirectory()));
1671 output.beginPage(getPageTitle("Source for " + classDoc.qualifiedTypeName()),
1675 output.beginBody(CssClass.BODY_CONTENT_SOURCE);
1677 printNavBarTop(output, "source", classDoc, null, null);
1679 output.div(CssClass.SOURCE_TITLE, "Source for " + classDoc.qualifiedTypeName());
1680 output.beginDiv(CssClass.SOURCE);
1681 output.print(sourceXhtml);
1682 output.endDiv(CssClass.SOURCE);
1684 printNavBarBottom(output, "source", classDoc);
1692 private void printHelpPage()
1695 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1696 "help" + filenameExtension),
1698 output.beginPage(getPageTitle("Help"),
1701 output.beginBody(CssClass.BODY_CONTENT_HELP);
1703 printNavBarTop(output, "help");
1706 if (null != optionHelpFile.getValue()){
1707 helpIn = new FileInputStream(optionHelpFile.getValue());
1710 helpIn = getClass().getResourceAsStream("/htmldoclet/help.xhtml");
1712 output.insert(new InputStreamReader(helpIn, "utf-8"));
1715 printNavBarBottom(output, "help");
1722 private void printOverviewPage()
1725 HtmlPage output = newHtmlPage(new File(getTargetDirectory(),
1726 "overview-summary" + filenameExtension),
1728 output.beginPage(getWindowTitle(),
1731 output.beginBody(CssClass.BODY_CONTENT_OVERVIEW);
1733 printNavBarTop(output, "overview");
1735 String overviewHeader;
1736 if (null != optionDocTitle.getValue()) {
1737 overviewHeader = optionDocTitle.getValue();
1739 else if (null != optionTitle.getValue()) {
1740 overviewHeader = optionTitle.getValue();
1743 overviewHeader = null;
1746 if (null != overviewHeader) {
1747 output.div(CssClass.OVERVIEW_TITLE, overviewHeader);
1750 output.beginDiv(CssClass.OVERVIEW_DESCRIPTION_TOP);
1751 printTags(output, getRootDoc(), getRootDoc().firstSentenceTags(), true);
1752 output.endDiv(CssClass.OVERVIEW_DESCRIPTION_TOP);
1754 List packageGroups = getPackageGroups();
1756 if (packageGroups.isEmpty()) {
1758 printOverviewPackages(output, getAllPackages(),
1762 Set otherPackages = new LinkedHashSet();
1763 otherPackages.addAll(getAllPackages());
1765 Iterator it = packageGroups.iterator();
1766 while (it.hasNext()) {
1767 PackageGroup packageGroup = (PackageGroup)it.next();
1768 printOverviewPackages(output,
1769 packageGroup.getPackages(),
1770 packageGroup.getName());
1771 otherPackages.removeAll(packageGroup.getPackages());
1774 if (!otherPackages.isEmpty()) {
1775 printOverviewPackages(output,
1781 output.anchorName("description");
1782 output.beginDiv(CssClass.OVERVIEW_DESCRIPTION_FULL);
1783 printTags(output, getRootDoc(), getRootDoc().inlineTags(), false);
1784 output.endDiv(CssClass.OVERVIEW_DESCRIPTION_FULL);
1786 printNavBarBottom(output, "overview");
1792 private void printOverviewPackages(HtmlPage output, Collection packageDocs, String header)
1794 output.beginDiv(CssClass.TABLE_CONTAINER);
1795 output.beginTable(CssClass.OVERVIEW_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
1796 output.rowDiv(CssClass.TABLE_HEADER, header);
1798 Iterator it = packageDocs.iterator();
1799 while (it.hasNext()) {
1800 PackageDoc packageDoc = (PackageDoc)it.next();
1803 output.beginCell(CssClass.OVERVIEW_SUMMARY_LEFT);
1804 output.beginAnchor(getPackageURL(packageDoc) + "package-summary" + filenameExtension);
1805 output.print(packageDoc.name());
1809 output.beginCell(CssClass.OVERVIEW_SUMMARY_RIGHT);
1810 printTags(output, packageDoc, packageDoc.firstSentenceTags(), true);
1815 output.endDiv(CssClass.TABLE_CONTAINER);
1818 private void printClassUsagePage(File packageDir, String pathToRoot, ClassDoc classDoc)
1821 HtmlPage output = newHtmlPage(new File(packageDir,
1822 classDoc.name() + "-uses" + filenameExtension),
1824 output.beginPage(getPageTitle(classDoc.name()), getOutputCharset(), getStylesheets());
1825 output.beginBody(CssClass.BODY_CONTENT_USES);
1826 printNavBarTop(output, "uses", classDoc, null, null);
1828 output.div(CssClass.USAGE_TITLE,
1829 "Uses of " + getClassTypeName(classDoc)
1830 + " " + classDoc.qualifiedName());
1832 Map packageToUsageTypeMap = getUsageOfClass(classDoc);
1833 if (null != packageToUsageTypeMap && !packageToUsageTypeMap.isEmpty()) {
1835 Iterator packagesIterator = packageToUsageTypeMap.keySet().iterator();
1836 while (packagesIterator.hasNext()) {
1837 PackageDoc packageDoc = (PackageDoc)packagesIterator.next();
1839 output.div(CssClass.USAGE_PACKAGE_TITLE, "Uses in package " + packageDoc.name());
1841 Map usageTypeToUsersMap = (Map)packageToUsageTypeMap.get(packageDoc);
1842 Iterator usageTypeIterator = usageTypeToUsersMap.keySet().iterator();
1843 while (usageTypeIterator.hasNext()) {
1844 UsageType usageType = (UsageType)usageTypeIterator.next();
1846 output.beginTable(CssClass.USAGE_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
1847 output.rowDiv(CssClass.USAGE_TABLE_HEADER, format("usagetype." + usageType.getId(),
1848 classDoc.qualifiedName()));
1850 Set users = (Set)usageTypeToUsersMap.get(usageType);
1851 Iterator userIterator = users.iterator();
1852 while (userIterator.hasNext()) {
1853 Doc user = (Doc)userIterator.next();
1857 if (user instanceof ClassDoc) {
1858 output.beginCell(CssClass.USAGE_SUMMARY_LEFT);
1859 output.print("class");
1862 output.beginCell(CssClass.USAGE_SUMMARY_RIGHT);
1863 output.beginDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
1864 printType(output, ((ClassDoc)user));
1865 output.endDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
1866 output.beginDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
1867 printTags(output, ((ClassDoc)user), ((ClassDoc)user).firstSentenceTags(), true);
1868 output.endDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
1871 else if (user instanceof FieldDoc) {
1872 FieldDoc fieldDoc = (FieldDoc)user;
1874 output.beginCell(CssClass.USAGE_SUMMARY_LEFT);
1875 printType(output, ((FieldDoc)user).type());
1878 output.beginCell(CssClass.USAGE_SUMMARY_RIGHT);
1879 output.beginDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
1880 printType(output, ((FieldDoc)user).containingClass());
1882 output.beginAnchor(getMemberDocURL(output, (FieldDoc)user));
1883 output.print(((FieldDoc)user).name());
1885 output.endDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
1886 output.beginDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
1887 printTags(output, ((FieldDoc)user), ((FieldDoc)user).firstSentenceTags(), true);
1888 output.endDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
1891 else if (user instanceof MethodDoc) {
1892 MethodDoc methodDoc = (MethodDoc)user;
1894 output.beginCell(CssClass.USAGE_SUMMARY_LEFT);
1895 printType(output, ((MethodDoc)user).returnType());
1898 output.beginCell(CssClass.USAGE_SUMMARY_RIGHT);
1899 output.beginDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
1900 printType(output, ((MethodDoc)user).containingClass());
1902 output.beginAnchor(getMemberDocURL(output, (MethodDoc)user));
1903 output.print(((MethodDoc)user).name());
1905 printParameters(output, (ExecutableMemberDoc)user);
1906 output.endDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
1907 output.beginDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
1908 printTags(output, ((MethodDoc)user), ((MethodDoc)user).firstSentenceTags(), true);
1909 output.endDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
1912 else if (user instanceof ConstructorDoc) {
1913 ConstructorDoc constructorDoc = (ConstructorDoc)user;
1915 output.beginCell(CssClass.USAGE_SUMMARY_RIGHT);
1916 output.beginDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
1917 printType(output, ((ConstructorDoc)user).containingClass());
1919 output.beginAnchor(getMemberDocURL(output, (ConstructorDoc)user));
1920 output.print(((ConstructorDoc)user).name());
1922 printParameters(output, (ExecutableMemberDoc)user);
1923 output.endDiv(CssClass.USAGE_SUMMARY_SYNOPSIS);
1924 output.beginDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
1925 printTags(output, ((ConstructorDoc)user),
1926 ((ConstructorDoc)user).firstSentenceTags(), true);
1927 output.endDiv(CssClass.USAGE_SUMMARY_DESCRIPTION);
1938 output.div(CssClass.USAGE_EMPTY,
1939 getClassTypeName(classDoc)
1940 + " " + classDoc.qualifiedName() + " is not used by any class in this documentation set.");
1942 printNavBarBottom(output, "uses", classDoc);
1948 private void printSuperTreeRec(HtmlPage output, ListIterator it, int level)
1950 if (it.hasPrevious()) {
1951 ClassDoc cd = (ClassDoc)it.previous();
1952 output.beginElement("li", new String[] { "class" }, new String[] { "inheritance " + level });
1953 output.beginElement("code");
1954 if (it.hasPrevious()) {
1955 printType(output, cd, true);
1958 output.print(cd.qualifiedName() + getTypeParameters(cd));
1960 output.endElement("code");
1961 output.endElement("li");
1963 output.beginElement("li");
1965 if (it.hasPrevious()) {
1966 output.beginElement("ul", new String[] { "class" }, new String[] { "inheritance " + (level + 1) });
1967 printSuperTreeRec(output, it, level + 1);
1968 output.endElement("ul");
1971 output.endElement("li");
1975 private static boolean isSubInterface(ClassDoc classDoc, ClassDoc otherClassDoc)
1977 ClassDoc[] interfaces = otherClassDoc.interfaces();
1978 for (int i=0; i<interfaces.length; ++i) {
1979 if (classDoc == interfaces[i]) {
1982 else if (isSubInterface(classDoc, interfaces[i])) {
1989 private void printCommaSeparatedTypes(HtmlPage output,
1994 if (!list.isEmpty()) {
1995 output.beginDiv(cssClass);
1996 output.div(CssClass.CLASS_KNOWNIMPLEMENTING_HEADER, header);
1997 output.beginDiv(CssClass.CLASS_KNOWNIMPLEMENTING_ITEM);
1998 Iterator it = list.iterator();
1999 while (it.hasNext()) {
2000 Type type = (Type)it.next();
2001 printType(output, type);
2006 output.endDiv(CssClass.CLASS_KNOWNIMPLEMENTING_ITEM);
2007 output.endDiv(cssClass);
2011 private void printClassPage(File packageDir, String pathToRoot,
2012 ClassDoc classDoc, ClassDoc prevClassDoc, ClassDoc nextClassDoc)
2015 HtmlPage output = newHtmlPage(new File(packageDir,
2016 classDoc.name() + filenameExtension),
2018 Set keywords = new LinkedHashSet();
2020 keywords.add(classDoc.qualifiedName() + " class");
2021 FieldDoc[] fieldDocs = classDoc.fields();
2022 for (int i=0; i<fieldDocs.length; ++i) {
2023 FieldDoc fieldDoc = fieldDocs[i];
2024 keywords.add(fieldDoc.name());
2027 MethodDoc[] methodDocs = classDoc.methods();
2028 for (int i=0; i<methodDocs.length; ++i) {
2029 MethodDoc methodDoc = methodDocs[i];
2030 keywords.add(methodDoc.name() + "()");
2033 String parameters = getTypeParameters(classDoc);
2035 output.beginPage(getPageTitle(classDoc.name()), getOutputCharset(),
2036 keywords, getStylesheets());
2037 output.beginBody(CssClass.BODY_CONTENT_CLASS);
2038 printNavBarTop(output, "class", classDoc, prevClassDoc, nextClassDoc);
2040 output.beginDiv(CssClass.CLASS_TITLE);
2041 output.div(CssClass.CLASS_TITLE_PACKAGE,
2042 classDoc.containingPackage().name());
2043 output.div(CssClass.CLASS_TITLE_CLASS,
2044 getClassTypeName(classDoc)
2045 + " " + classDoc.name()
2047 output.endDiv(CssClass.CLASS_TITLE);
2049 boolean needSep = false;
2051 if (classDoc.isInterface()) {
2053 InterfaceRelation relation
2054 = (InterfaceRelation)getInterfaceRelations().get(classDoc);
2056 printCommaSeparatedTypes(output,
2057 relation.superInterfaces,
2058 "All Superinterfaces:",
2059 CssClass.CLASS_KNOWNIMPLEMENTING);
2061 printCommaSeparatedTypes(output,
2062 relation.subInterfaces,
2063 "Known Subinterfaces:",
2064 CssClass.CLASS_KNOWNIMPLEMENTING);
2066 printCommaSeparatedTypes(output,
2067 relation.implementingClasses,
2068 "Known Implementing Classes:",
2069 CssClass.CLASS_KNOWNIMPLEMENTING);
2071 needSep = !relation.superInterfaces.isEmpty()
2072 || !relation.subInterfaces.isEmpty()
2073 || !relation.implementingClasses.isEmpty();
2078 if (!"java.lang.Object".equals(classDoc.qualifiedName())) {
2079 LinkedList superClasses = new LinkedList();
2080 for (ClassDoc cd = classDoc; cd != null; cd = cd.superclass()) {
2081 superClasses.add(cd);
2083 output.beginDiv(CssClass.CLASS_INHERITANCETREE);
2084 output.beginElement("ul", new String[] { "class" }, new String[] { "inheritance 0" });
2085 printSuperTreeRec(output, superClasses.listIterator(superClasses.size()), 0);
2086 output.endElement("ul");
2087 output.endDiv(CssClass.CLASS_INHERITANCETREE);
2089 if (null != classDoc.containingClass()) {
2090 output.beginDiv(CssClass.CLASS_ENCLOSINGCLASS);
2091 output.div(CssClass.CLASS_ENCLOSINGCLASS_HEADER, "Enclosing Class:");
2092 output.beginDiv(CssClass.CLASS_ENCLOSINGCLASS_ITEM);
2093 printType(output, classDoc.containingClass());
2094 output.endDiv(CssClass.CLASS_ENCLOSINGCLASS_ITEM);
2095 output.endDiv(CssClass.CLASS_ENCLOSINGCLASS);
2098 Set implementedInterfaces = getImplementedInterfaces(classDoc);
2100 printCommaSeparatedTypes(output,
2101 implementedInterfaces,
2102 "Implemented Interfaces:",
2103 CssClass.CLASS_KNOWNIMPLEMENTING);
2105 List knownDirectSubclasses = getKnownDirectSubclasses(classDoc);
2106 if (!knownDirectSubclasses.isEmpty()) {
2107 output.beginDiv(CssClass.CLASS_SUBCLASSES);
2108 output.div(CssClass.CLASS_SUBCLASSES_HEADER, "Known Direct Subclasses:");
2109 output.beginDiv(CssClass.CLASS_SUBCLASSES_ITEM);
2110 Iterator it = knownDirectSubclasses.iterator();
2111 while (it.hasNext()) {
2112 printType(output, (ClassDoc)it.next());
2118 output.endDiv(CssClass.CLASS_SUBCLASSES_ITEM);
2119 output.endDiv(CssClass.CLASS_SUBCLASSES_HEADER);
2120 output.endDiv(CssClass.CLASS_SUBCLASSES);
2129 output.beginDiv(CssClass.CLASS_SYNOPSIS);
2130 output.beginDiv(CssClass.CLASS_SYNOPSIS_DECLARATION);
2131 output.print(getFullModifiers(classDoc) + ' ' + getClassTypeKeyword(classDoc)
2133 output.beginSpan(CssClass.CLASS_SYNOPSIS_NAME);
2134 if (optionLinkSource.getValue() && null != classDoc.position()) {
2135 output.beginAnchor(getOuterClassDoc(classDoc).name() + "-source" + filenameExtension + "#line." + classDoc.position());
2136 output.print(classDoc.name() + parameters);
2140 output.print(classDoc.name() + parameters);
2142 output.endSpan(CssClass.CLASS_SYNOPSIS_NAME);
2143 output.endDiv(CssClass.CLASS_SYNOPSIS_DECLARATION);
2145 if (!classDoc.isInterface()) {
2146 if (null != classDoc.superclass()) {
2147 output.beginDiv(CssClass.CLASS_SYNOPSIS_SUPERCLASS);
2148 output.print("extends ");
2149 printType(output, classDoc.superclass());
2150 output.endDiv(CssClass.CLASS_SYNOPSIS_SUPERCLASS);
2154 ClassDoc[] interfaces = classDoc.interfaces();
2155 if (interfaces.length > 0) {
2156 output.beginDiv(CssClass.CLASS_SYNOPSIS_IMPLEMENTS);
2157 if (!classDoc.isInterface()) {
2158 output.print("implements ");
2161 output.print("extends ");
2163 for (int i=0; i<interfaces.length; ++i) {
2167 printType(output, interfaces[i]);
2169 output.endDiv(CssClass.CLASS_SYNOPSIS_IMPLEMENTS);
2171 output.endDiv(CssClass.CLASS_SYNOPSIS);
2175 if (!optionNoComment.getValue()) {
2176 output.beginDiv(CssClass.CLASS_DESCRIPTION);
2177 printTags(output, classDoc, classDoc.inlineTags(), false);
2178 output.endDiv(CssClass.CLASS_DESCRIPTION);
2180 printTaglets(output, classDoc.tags(), new HtmlTagletContext(classDoc, output, false));
2184 Set implementedInterfaces = getImplementedInterfaces(classDoc);
2186 boolean haveInheritedFields = false;
2187 boolean haveInheritedMethods = false;
2188 boolean haveInheritedClasses = false;
2190 if (!classDoc.isInterface()) {
2191 ClassDoc superClassDoc = classDoc.superclass();
2192 while (null != superClassDoc
2193 && (!haveInheritedFields
2194 || !haveInheritedMethods
2195 || !haveInheritedClasses)) {
2196 if (superClassDoc.fields().length > 0) {
2197 haveInheritedFields = true;
2199 if (superClassDoc.methods().length > 0) {
2200 haveInheritedMethods = true;
2202 if (superClassDoc.innerClasses().length > 0) {
2203 haveInheritedClasses = true;
2205 superClassDoc = superClassDoc.superclass();
2210 printProgramElementDocs(output, getSortedInnerClasses(classDoc),
2211 "Nested Class Summary", haveInheritedClasses,
2215 ClassDoc superClassDoc = classDoc.superclass();
2216 while (null != superClassDoc) {
2217 printInheritedMembers(output, getSortedInnerClasses(superClassDoc),
2218 "Nested classes/interfaces inherited from class {0}",
2220 superClassDoc = superClassDoc.superclass();
2224 printProgramElementDocs(output, getSortedFields(classDoc),
2225 "Field Summary", haveInheritedFields,
2229 ClassDoc superClassDoc = classDoc.superclass();
2230 while (null != superClassDoc) {
2231 printInheritedMembers(output, getSortedFields(superClassDoc),
2232 "Fields inherited from class {0}",
2234 superClassDoc = superClassDoc.superclass();
2239 Iterator it = implementedInterfaces.iterator();
2240 while (it.hasNext()) {
2241 ClassDoc implementedInterface
2242 = (ClassDoc)it.next();
2243 if (!"java.io.Serializable".equals(implementedInterface.qualifiedName())
2244 && !"java.io.Externalizable".equals(implementedInterface.qualifiedName())) {
2245 printInheritedMembers(output, getSortedFields(implementedInterface),
2246 "Fields inherited from interface {0}",
2247 implementedInterface);
2252 printProgramElementDocs(output, getSortedConstructors(classDoc),
2253 "Constructor Summary", false,
2254 "summary-constructors");
2255 printProgramElementDocs(output, getSortedMethods(classDoc),
2256 "Method Summary", haveInheritedMethods,
2259 if (classDoc.isInterface()) {
2260 InterfaceRelation relation
2261 = (InterfaceRelation)getInterfaceRelations().get(classDoc);
2262 Iterator it = relation.superInterfaces.iterator();
2263 while (it.hasNext()) {
2264 ClassDoc superClassDoc = (ClassDoc)it.next();
2265 printInheritedMembers(output, getSortedMethods(superClassDoc),
2266 "Methods inherited from interface {0}",
2271 ClassDoc superClassDoc = classDoc.superclass();
2272 while (null != superClassDoc) {
2273 printInheritedMembers(output, getSortedMethods(superClassDoc),
2274 "Methods inherited from class {0}",
2276 superClassDoc = superClassDoc.superclass();
2280 printMemberDetails(output, getSortedFields(classDoc),
2281 "Field Details", false, "detail-fields");
2282 printMemberDetails(output, getSortedConstructors(classDoc),
2283 "Constructor Details", false, "detail-constructors");
2284 printMemberDetails(output, getSortedMethods(classDoc),
2285 "Method Details", false, "detail-methods");
2287 printNavBarBottom(output, "class", classDoc);
2294 private void printInheritedMembers(HtmlPage output,
2295 ProgramElementDoc[] memberDocs,
2296 String headerFormat,
2297 ClassDoc superclass)
2299 if (memberDocs.length > 0) {
2301 output.beginDiv(CssClass.TABLE_CONTAINER);
2302 output.beginTable(CssClass.CLASS_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
2303 String superclassLink;
2304 if (superclass.isIncluded()) {
2305 superclassLink = superclass.containingPackage().name()
2306 + "." + createTypeHref(output, superclass, false);
2309 superclassLink = createTypeHref(output, superclass, true);
2311 output.rowDiv(CssClass.TABLE_SUB_HEADER,
2312 new MessageFormat(headerFormat).format(new Object[] {
2317 output.beginCell(CssClass.CLASS_SUMMARY_INHERITED);
2318 for (int i=0; i<memberDocs.length; ++i) {
2319 ProgramElementDoc memberDoc = memberDocs[i];
2323 String title = null;
2324 if (memberDoc.isMethod()) {
2325 title = memberDoc.name() + ((MethodDoc)memberDoc).flatSignature();
2327 else if (memberDoc.isInterface()) {
2328 title = "interface " + ((ClassDoc)memberDoc).qualifiedName();
2330 else if (memberDoc.isClass()) {
2331 title = "class " + ((ClassDoc)memberDoc).qualifiedName();
2333 output.beginAnchor(getMemberDocURL(output, memberDoc), title);
2334 output.beginSpan(CssClass.CLASS_SUMMARY_INHERITED_MEMBER);
2335 output.print(memberDoc.name());
2336 output.endSpan(CssClass.CLASS_SUMMARY_INHERITED_MEMBER);
2342 output.endDiv(CssClass.TABLE_CONTAINER);
2346 private void collectSpecifiedByRecursive(Set specifyingInterfaces,
2348 MethodDoc methodDoc)
2350 ClassDoc[] interfaces = classDoc.interfaces();
2351 for (int i=0; i<interfaces.length; ++i) {
2352 MethodDoc[] methods = interfaces[i].methods();
2353 for (int j=0; j<methods.length; ++j) {
2354 if (methods[j].name().equals(methodDoc.name())
2355 && methods[j].signature().equals(methodDoc.signature())) {
2356 specifyingInterfaces.add(methods[j]);
2360 collectSpecifiedByRecursive(specifyingInterfaces,
2366 private void printMemberDetails(HtmlPage output,
2367 ProgramElementDoc[] memberDocs, String header,
2368 boolean isOnSerializedPage,
2371 if (memberDocs.length > 0) {
2373 if (null != anchor) {
2374 output.anchorName(anchor);
2377 CssClass sectionClass;
2378 CssClass headerClass;
2379 if (isOnSerializedPage) {
2380 sectionClass = CssClass.SERIALIZED_SECTION;
2381 headerClass = CssClass.SERIALIZED_SECTION_HEADER;
2384 sectionClass = CssClass.SECTION;
2385 headerClass = CssClass.SECTION_HEADER;
2387 output.div(headerClass, header);
2388 output.beginDiv(sectionClass);
2390 for (int i=0; i<memberDocs.length; ++i) {
2395 ProgramElementDoc memberDoc = memberDocs[i];
2397 output.anchorName(getMemberAnchor(memberDoc));
2399 output.beginDiv(CssClass.MEMBER_DETAIL);
2400 output.div(CssClass.MEMBER_DETAIL_NAME, memberDoc.name());
2402 StringBuffer synopsis = new StringBuffer();
2403 int synopsisLength = 0;
2405 if (!isOnSerializedPage || !memberDoc.isField()) {
2406 String fullModifiers = getFullModifiers(memberDoc);
2407 synopsis.append(fullModifiers);
2408 synopsisLength += fullModifiers.length();
2411 if (memberDoc.isMethod() || memberDoc.isField()) {
2413 if (memberDoc.isMethod()) {
2414 type = ((MethodDoc)memberDoc).returnType();
2417 type = ((FieldDoc)memberDoc).type();
2420 synopsis.append(" ");
2422 synopsis.append(createTypeHref(output, type, false));
2423 if (null != type.asClassDoc() && type.asClassDoc().isIncluded()) {
2424 synopsisLength += type.asClassDoc().name().length();
2427 synopsisLength += type.qualifiedTypeName().length();
2429 synopsisLength += type.dimension().length();
2432 synopsis.append(" ");
2435 if (optionLinkSource.getValue() && null != memberDoc.position()) {
2436 ClassDoc containingClass = memberDoc.containingClass();
2437 while (null != containingClass.containingClass()) {
2438 containingClass = containingClass.containingClass();
2440 String href = containingClass.name() + "-source" + filenameExtension + "#line." + memberDoc.position().line();
2441 synopsis.append(output.createHrefString(href, memberDoc.name()));
2444 synopsis.append(memberDoc.name());
2446 synopsisLength += memberDoc.name().length();
2448 if (memberDoc.isConstructor() || memberDoc.isMethod()) {
2449 //printParameters(output, (ExecutableMemberDoc)memberDoc);
2450 synopsis.append("(");
2452 StringBuffer paddingLeft = new StringBuffer();
2453 for (int j=0; j<synopsisLength; ++j) {
2454 paddingLeft.append(' ');
2456 Parameter[] parameters = ((ExecutableMemberDoc)memberDoc).parameters();
2457 for (int j=0; j<parameters.length; ++j) {
2458 Parameter parameter = parameters[j];
2459 synopsis.append(createTypeHref(output, parameter.type(), false));
2460 synopsis.append(" ");
2461 synopsis.append(parameter.name());
2462 if (j < parameters.length - 1) {
2463 synopsis.append(",\n");
2464 synopsis.append(paddingLeft);
2467 synopsis.append(")");
2468 ClassDoc[] exceptions = ((ExecutableMemberDoc)memberDoc).thrownExceptions();
2469 if (exceptions.length > 0) {
2470 synopsis.append("\n throws ");
2471 for (int j=0; j<exceptions.length; ++j) {
2472 ClassDoc exception = exceptions[j];
2473 synopsis.append(createTypeHref(output, exception, false));
2474 if (j < exceptions.length - 1) {
2475 synopsis.append(",\n ");
2481 output.beginDiv(CssClass.MEMBER_DETAIL_SYNOPSIS);
2482 output.print(synopsis.toString());
2483 output.endDiv(CssClass.MEMBER_DETAIL_SYNOPSIS);
2485 output.beginDiv(CssClass.MEMBER_DETAIL_BODY);
2487 Tag[] deprecatedTags = memberDoc.tags("deprecated");
2488 if (deprecatedTags.length > 0) {
2489 output.beginDiv(CssClass.DEPRECATED_INLINE);
2490 output.beginSpan(CssClass.DEPRECATED_HEADER);
2491 output.print("Deprecated. ");
2492 output.endSpan(CssClass.DEPRECATED_HEADER);
2493 output.beginSpan(CssClass.DEPRECATED_BODY);
2495 for (int j=0; j<deprecatedTags.length; ++j) {
2496 printTags(output, memberDoc, deprecatedTags[j].inlineTags(), true);
2498 if (deprecatedTags.length > 0) {
2499 output.endSpan(CssClass.DEPRECATED_BODY);
2500 output.beginDiv(CssClass.DEPRECATED_INLINE);
2503 output.beginDiv(CssClass.MEMBER_DETAIL_DESCRIPTION);
2504 printTags(output, memberDoc, memberDoc.inlineTags(), false);
2505 output.endDiv(CssClass.MEMBER_DETAIL_DESCRIPTION);
2507 if (memberDoc.isConstructor() || memberDoc.isMethod()) {
2509 if (memberDoc.isMethod()) {
2510 Set specifyingInterfaces = new LinkedHashSet();
2511 if (memberDoc.containingClass().isInterface()) {
2512 collectSpecifiedByRecursive(specifyingInterfaces,
2513 memberDoc.containingClass(),
2514 (MethodDoc)memberDoc);
2517 for (ClassDoc cd = memberDoc.containingClass();
2518 null != cd; cd = cd.superclass()) {
2519 collectSpecifiedByRecursive(specifyingInterfaces,
2521 (MethodDoc)memberDoc);
2525 if (!specifyingInterfaces.isEmpty()
2526 && !isOnSerializedPage) {
2527 output.beginDiv(CssClass.MEMBER_DETAIL_SPECIFIED_BY_LIST);
2528 output.div(CssClass.MEMBER_DETAIL_SPECIFIED_BY_HEADER, "Specified by:");
2529 Iterator it = specifyingInterfaces.iterator();
2530 while (it.hasNext()) {
2531 MethodDoc specifyingInterfaceMethod = (MethodDoc)it.next();
2532 output.beginDiv(CssClass.MEMBER_DETAIL_SPECIFIED_BY_ITEM);
2533 output.beginAnchor(getMemberDocURL(output,
2534 specifyingInterfaceMethod));
2535 output.print(memberDoc.name());
2537 output.print(" in interface ");
2538 printType(output, specifyingInterfaceMethod.containingClass());
2539 output.endDiv(CssClass.MEMBER_DETAIL_SPECIFIED_BY_ITEM);
2541 output.endDiv(CssClass.MEMBER_DETAIL_SPECIFIED_BY_LIST);
2544 ClassDoc overriddenClassDoc = null;
2545 MemberDoc specifyingSuperMethod = null;
2547 for (ClassDoc superclassDoc = memberDoc.containingClass().superclass();
2548 null != superclassDoc && null == overriddenClassDoc;
2549 superclassDoc = superclassDoc.superclass()) {
2551 MethodDoc[] methods = superclassDoc.methods();
2552 for (int j=0; j<methods.length; ++j) {
2553 if (methods[j].name().equals(memberDoc.name())
2554 && methods[j].signature().equals(((MethodDoc)memberDoc).signature())) {
2555 overriddenClassDoc = superclassDoc;
2556 specifyingSuperMethod = methods[j];
2562 if (null != overriddenClassDoc) {
2563 output.beginDiv(CssClass.MEMBER_DETAIL_OVERRIDDEN_LIST);
2564 output.div(CssClass.MEMBER_DETAIL_OVERRIDDEN_HEADER, "Overrides:");
2565 output.beginDiv(CssClass.MEMBER_DETAIL_OVERRIDDEN_ITEM);
2567 output.beginAnchor(getMemberDocURL(output,
2568 specifyingSuperMethod));
2569 output.print(memberDoc.name());
2571 output.print(" in interface ");
2572 printType(output, overriddenClassDoc);
2574 output.endDiv(CssClass.MEMBER_DETAIL_OVERRIDDEN_ITEM);
2575 output.endDiv(CssClass.MEMBER_DETAIL_OVERRIDDEN_LIST);
2579 if (!optionNoComment.getValue()) {
2581 ExecutableMemberDoc execMemberDoc
2582 = (ExecutableMemberDoc)memberDoc;
2584 if (execMemberDoc.paramTags().length > 0) {
2585 output.beginDiv(CssClass.MEMBER_DETAIL_PARAMETER_LIST);
2586 output.div(CssClass.MEMBER_DETAIL_PARAMETER_HEADER, "Parameters:");
2587 Parameter[] parameters = execMemberDoc.parameters();
2588 for (int j=0; j<parameters.length; ++j) {
2589 Parameter parameter = parameters[j];
2590 ParamTag[] paramTags = execMemberDoc.paramTags();
2591 ParamTag paramTag = null;
2592 for (int k=0; k<paramTags.length; ++k) {
2593 if (paramTags[k].parameterName().equals(parameter.name())) {
2594 paramTag = paramTags[k];
2599 if (null != paramTag) {
2600 output.beginDiv(CssClass.MEMBER_DETAIL_PARAMETER_ITEM);
2601 output.beginSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_NAME);
2602 output.print(parameter.name());
2603 output.endSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_NAME);
2604 output.beginSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_SEPARATOR);
2605 output.print(" - ");
2606 output.endSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_SEPARATOR);
2607 output.beginSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_DESCRIPTION);
2608 printTags(output, execMemberDoc, paramTag.inlineTags(), false);
2609 output.endSpan(CssClass.MEMBER_DETAIL_PARAMETER_ITEM_DESCRIPTION);
2610 output.endDiv(CssClass.MEMBER_DETAIL_PARAMETER_ITEM);
2613 output.endDiv(CssClass.MEMBER_DETAIL_PARAMETER_LIST);
2616 if (execMemberDoc.isMethod()
2617 && !"void".equals(((MethodDoc)execMemberDoc).returnType().typeName())) {
2619 Tag[] returnTags = execMemberDoc.tags("return");
2620 if (returnTags.length > 0) {
2621 Tag returnTag = returnTags[0];
2623 output.beginDiv(CssClass.MEMBER_DETAIL_RETURN_LIST);
2624 output.div(CssClass.MEMBER_DETAIL_RETURN_HEADER, "Returns:");
2625 output.beginDiv(CssClass.MEMBER_DETAIL_RETURN_ITEM);
2627 printTags(output, execMemberDoc, returnTag.inlineTags(), false);
2629 output.endDiv(CssClass.MEMBER_DETAIL_RETURN_ITEM);
2630 output.endDiv(CssClass.MEMBER_DETAIL_RETURN_LIST);
2634 Set thrownExceptions = getThrownExceptions(execMemberDoc);
2635 boolean haveThrowsInfo = false;
2636 ThrowsTag[] throwsTags = execMemberDoc.throwsTags();
2637 for (int k=0; k<throwsTags.length; ++k) {
2638 ThrowsTag throwsTag = throwsTags[k];
2639 if (null != throwsTags[k].exception()
2640 && (isUncheckedException(throwsTags[k].exception())
2641 || thrownExceptions.contains(throwsTag.exception()))) {
2642 haveThrowsInfo = true;
2647 if (haveThrowsInfo) {
2648 output.beginDiv(CssClass.MEMBER_DETAIL_THROWN_LIST);
2649 output.div(CssClass.MEMBER_DETAIL_THROWN_HEADER, "Throws:");
2651 for (int k=0; k<throwsTags.length; ++k) {
2652 ThrowsTag throwsTag = throwsTags[k];
2653 if (null != throwsTag.exception()
2654 && (isUncheckedException(throwsTag.exception())
2655 || thrownExceptions.contains(throwsTag.exception()))) {
2656 output.beginDiv(CssClass.MEMBER_DETAIL_THROWN_ITEM);
2657 output.beginSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_NAME);
2658 printType(output, throwsTags[k].exception());
2659 output.endSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_NAME);
2660 if (null != throwsTag) {
2661 output.beginSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_SEPARATOR);
2662 output.print(" - ");
2663 output.endSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_SEPARATOR);
2664 output.beginSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_DESCRIPTION);
2665 printTags(output, execMemberDoc, throwsTag.inlineTags(), false);
2666 output.endSpan(CssClass.MEMBER_DETAIL_THROWN_ITEM_DESCRIPTION);
2668 output.endDiv(CssClass.MEMBER_DETAIL_THROWN_ITEM);
2671 output.endDiv(CssClass.MEMBER_DETAIL_THROWN_LIST);
2676 if (!optionNoComment.getValue()) {
2678 if (memberDoc.isField()) {
2679 FieldDoc fieldDoc = ((FieldDoc)memberDoc);
2680 if (null != fieldDoc.constantValue()) {
2681 output.beginDiv(CssClass.MEMBER_DETAIL_THROWN_LIST);
2682 output.div(CssClass.MEMBER_DETAIL_THROWN_HEADER, "Field Value:");
2683 output.div(CssClass.MEMBER_DETAIL_THROWN_ITEM,
2684 fieldDoc.constantValueExpression().toString());
2685 output.endDiv(CssClass.MEMBER_DETAIL_THROWN_LIST);
2689 TagletContext context = new HtmlTagletContext(memberDoc, output, isOnSerializedPage);
2690 printTaglets(output, memberDoc.tags(), context);
2693 output.endDiv(CssClass.MEMBER_DETAIL_BODY);
2694 output.endDiv(CssClass.MEMBER_DETAIL);
2696 output.endDiv(sectionClass);
2701 private void printParameters(HtmlPage output, ExecutableMemberDoc memberDoc)
2703 Parameter[] parameters = memberDoc.parameters();
2705 for (int j=0; j<parameters.length; ++j) {
2709 printType(output, parameters[j].type());
2710 output.print(" ");
2711 output.print(parameters[j].name());
2716 private void printProgramElementDocs(HtmlPage output,
2717 ProgramElementDoc[] memberDocs,
2719 boolean forceOutputHeader,
2722 if (memberDocs.length > 0 || forceOutputHeader) {
2723 output.anchorName(anchor);
2724 output.beginDiv(CssClass.TABLE_CONTAINER);
2725 output.beginTable(CssClass.CLASS_SUMMARY, new String[] { "border", "width" }, new String[] { "1", "100%" });
2726 output.rowDiv(CssClass.TABLE_HEADER, header);
2728 for (int i=0; i<memberDocs.length; ++i) {
2729 ProgramElementDoc memberDoc = memberDocs[i];
2732 if (!memberDoc.isConstructor()) {
2733 output.beginCell(CssClass.CLASS_SUMMARY_LEFT);
2734 output.beginDiv(CssClass.CLASS_SUMMARY_LEFT_SYNOPSIS);
2735 output.print(getSummaryModifiers(memberDoc) + " ");
2736 if (memberDoc.isMethod()) {
2737 printType(output, ((MethodDoc)memberDoc).returnType());
2739 else if (memberDoc.isField()) {
2740 printType(output, ((FieldDoc)memberDoc).type());
2742 else if (memberDoc.isInterface()) {
2743 output.print(" interface");
2745 else if (memberDoc.isClass()) {
2746 output.print(" class");
2748 output.endDiv(CssClass.CLASS_SUMMARY_LEFT_SYNOPSIS);
2752 output.beginCell(CssClass.CLASS_SUMMARY_RIGHT);
2753 output.beginDiv(CssClass.CLASS_SUMMARY_RIGHT_LIST);
2754 output.beginDiv(CssClass.CLASS_SUMMARY_RIGHT_SYNOPSIS);
2755 if (memberDoc.isClass() || memberDoc.isInterface()) {
2756 output.beginAnchor(getClassDocURL(output, (ClassDoc)memberDoc));
2759 output.beginAnchor("#" + getMemberAnchor(memberDoc));
2761 output.print(memberDoc.name());
2763 if (memberDoc.isConstructor() || memberDoc.isMethod()) {
2764 printParameters(output, (ExecutableMemberDoc)memberDoc);
2766 output.endDiv(CssClass.CLASS_SUMMARY_RIGHT_SYNOPSIS);
2767 Tag[] firstSentenceTags;
2768 Tag[] deprecatedTags = memberDoc.tags("deprecated");
2769 if (deprecatedTags.length > 0) {
2770 firstSentenceTags = deprecatedTags[0].firstSentenceTags();
2773 firstSentenceTags = memberDoc.firstSentenceTags();
2776 if (null != firstSentenceTags && firstSentenceTags.length > 0) {
2777 output.beginDiv(CssClass.CLASS_SUMMARY_RIGHT_DESCRIPTION);
2778 if (deprecatedTags.length > 0) {
2779 output.beginDiv(CssClass.DEPRECATED);
2780 output.beginSpan(CssClass.DEPRECATED_HEADER);
2781 output.print("Deprecated. ");
2782 output.endSpan(CssClass.DEPRECATED_HEADER);
2783 output.beginSpan(CssClass.DEPRECATED_BODY);
2785 printTags(output, memberDoc, firstSentenceTags, true);
2786 if (deprecatedTags.length > 0) {
2787 output.endSpan(CssClass.DEPRECATED_BODY);
2788 output.beginDiv(CssClass.DEPRECATED);
2790 output.endDiv(CssClass.CLASS_SUMMARY_RIGHT_DESCRIPTION);
2792 output.endDiv(CssClass.CLASS_SUMMARY_RIGHT_LIST);
2797 output.endDiv(CssClass.TABLE_CONTAINER);
2801 private void printTag(final HtmlPage output,
2802 HtmlRepairer repairer,
2803 Tag tag, boolean firstSentence,
2807 TagletContext context = new HtmlTagletContext(contextDoc, output, false);
2808 if (firstSentence) {
2809 output.print(renderInlineTags(tag.firstSentenceTags(), context));
2812 output.print(renderInlineTags(tag.inlineTags(), context));
2816 private void printTags(HtmlPage output, Doc contextDoc, Tag[] tags, boolean firstSentence)
2818 printTags(output, contextDoc, tags, firstSentence, false);
2821 private void printTags(HtmlPage output, Doc contextDoc, Tag[] tags, boolean firstSentence, boolean inline)
2823 if (!optionNoComment.getValue()) {
2824 output.print(renderInlineTags(tags, new HtmlTagletContext(contextDoc, output, false)));
2828 if (!optionNoComment.getValue()) {
2829 output.print(renderInlineTags(tag.firstSentenceTags(), output));
2830 HtmlRepairer repairer = new HtmlRepairer(getRootDoc(),
2834 for (int i=0; i<tags.length; ++i) {
2835 printTag(output, repairer, tags[i], firstSentence, inline);
2837 output.print(repairer.terminateText());
2842 private String getClassDocURL(HtmlPage output, ClassDoc classDoc)
2844 return output.getPathToRoot()
2846 + getPackageURL(classDoc.containingPackage())
2847 + classDoc.name() + filenameExtension;
2850 private String getMemberDocURL(HtmlPage output, ProgramElementDoc memberDoc)
2852 ClassDoc classDoc = memberDoc.containingClass();
2853 PackageDoc packageDoc = classDoc.containingPackage();
2854 ExternalDocSet externalDocSet = null;
2855 if (classDoc.containingPackage().name().length() > 0) {
2856 externalDocSet = (ExternalDocSet)packageNameToDocSet.get(packageDoc.name());
2858 StringBuffer result = new StringBuffer();
2859 result.append(getClassDocURL(output, classDoc));
2861 if (null == externalDocSet) {
2862 result.append(getMemberAnchor(memberDoc));
2865 result.append(getMemberAnchor(memberDoc, externalDocSet.isJavadocCompatible()));
2867 return result.toString();
2870 private void printType(HtmlPage output, Type type)
2872 printType(output, type, false);
2875 private void printType(HtmlPage output, Type type, boolean fullyQualified)
2877 output.print(createTypeHref(output, type, fullyQualified));
2880 private String createTypeHref(HtmlPage output, Type type, boolean fullyQualified)
2882 ClassDoc asClassDoc = type.asClassDoc();
2884 if (null != asClassDoc && asClassDoc.isIncluded()) {
2885 url = getClassDocURL(output, asClassDoc);
2887 else if (!type.isPrimitive()) {
2888 if (type.qualifiedTypeName().length() > type.typeName().length()) {
2889 String packageName = type.qualifiedTypeName();
2890 packageName = packageName.substring(0, packageName.length() - type.typeName().length() - 1);
2892 ExternalDocSet externalDocSet
2893 = (ExternalDocSet)packageNameToDocSet.get(packageName);
2894 if (null != externalDocSet) {
2895 url = externalDocSet.getClassDocURL(packageName, type.typeName());
2900 StringBuffer result = new StringBuffer();
2902 if (null != url && null != asClassDoc) {
2903 String parameters = getTypeParameters(asClassDoc);
2904 if (fullyQualified) {
2905 result.append(output.createHrefString(url,possiblyQualifiedName(asClassDoc) + parameters));
2908 StringBuffer title = new StringBuffer();
2909 title.append(getClassTypeName(asClassDoc));
2910 title.append(" in ");
2911 title.append(asClassDoc.containingPackage().name());
2912 result.append(output.createHrefString(url, asClassDoc.name() + parameters, title.toString()));
2916 result.append(possiblyQualifiedName(type));
2918 result.append(type.dimension());
2919 return result.toString();
2922 private void printTaglets(final HtmlPage output, Tag[] tags, TagletContext context)
2924 super.printMainTaglets(tags, context, new TagletPrinter() {
2925 public void printTagletString(String tagletString) {
2926 output.beginDiv(CssClass.TAGLET);
2927 output.print(tagletString);
2928 output.endDiv(CssClass.TAGLET);
2933 private String getPackageURL(PackageDoc packageDoc)
2935 if (packageDoc.name().length() > 0) {
2936 ExternalDocSet externalDocSet = (ExternalDocSet)packageNameToDocSet.get(packageDoc.name());
2938 if (null != externalDocSet) {
2939 url = externalDocSet.getPackageDocURL(packageDoc.name());
2942 url = packageDoc.name().replace('.', '/');
2944 if (!url.endsWith("/")) {
2956 private String getClassURL(ClassDoc classDoc)
2958 ExternalDocSet externalDocSet = null;
2959 if (classDoc.containingPackage().name().length() > 0) {
2960 externalDocSet = (ExternalDocSet)packageNameToDocSet.get(classDoc.containingPackage().name());
2962 if (null != externalDocSet) {
2963 return externalDocSet.getClassDocURL(classDoc.containingPackage().name(),
2967 return getPackageURL(classDoc.containingPackage()) + classDoc.name() + filenameExtension;
2971 protected void run()
2972 throws DocletConfigurationException, IOException
2974 if (optionSerialWarn.getValue()) {
2975 printWarning("Option -serialwarn is currently ignored.");
2978 if (null != optionTitle.getValue()) {
2979 printWarning("Option -title is deprecated.");
2982 if (!optionValidHtml.getValue()) {
2983 printWarning("Option -validhtml hasn't been specified. Generated HTML will not validate.");
2988 boolean warningEmitted = false;
2989 Iterator it = externalDocSets.iterator();
2990 while (it.hasNext()) {
2991 ExternalDocSet externalDocSet = (ExternalDocSet)it.next();
2992 printNotice("Fetching package list for external documentation set.");
2994 externalDocSet.load(getTargetDirectory());
2995 if (!isJavadocCompatibleNames() && externalDocSet.isJavadocCompatible()
2996 && !warningEmitted) {
2997 printWarning("Linking to javadoc-compatible documentation. Generated HTML will not validate ");
2998 warningEmitted = true;
3001 catch (FileNotFoundException e) {
3002 printWarning("Cannot fetch package list from " + externalDocSet.getPackageListDir());
3004 Iterator pit = externalDocSet.getPackageNames().iterator();
3005 while (pit.hasNext()) {
3006 String packageName = (String)pit.next();
3007 packageNameToDocSet.put(packageName, externalDocSet);
3011 printNotice("Building cross-reference information...");
3012 getInterfaceRelations();
3015 printNotice("Writing overview files...");
3016 printFrameSetPage();
3017 if (!isSinglePackage()) {
3018 printPackagesMenuPage();
3019 printAllClassesMenuPage();
3020 printOverviewPage();
3021 if (!optionNoTree.getValue()) {
3022 printNotice("Writing full tree...");
3023 printFullTreePage();
3026 printPackagesListFile();
3028 if (!optionNoIndex.getValue()) {
3029 printNotice("Writing index...");
3030 if (!optionSplitIndex.getValue()) {
3037 if (outputHelpPage && !optionNoHelp.getValue()) {
3043 File resourcesDir = new File(getTargetDirectory(),
3046 if ((resourcesDir.exists() && !resourcesDir.isDirectory())
3047 || (!resourcesDir.exists() && !resourcesDir.mkdirs())) {
3048 throw new IOException("Cannot create directory " + resourcesDir);
3053 String[] resourceNames = {
3055 "gjdochtml-clean-layout.css",
3056 "gjdochtml-clean-color1.css",
3058 "xhtml11-target10.dtd",
3061 for (int i=0; i<resourceNames.length; ++i) {
3062 String resourceName = resourceNames[i];
3063 File targetFile = new File(resourcesDir,
3065 InputStream in = getClass().getResourceAsStream("/htmldoclet/" + resourceName);
3067 in = new FileInputStream("src/resources/htmldoclet/" + resourceName);
3069 FileOutputStream out = new FileOutputStream(targetFile);
3070 IOToolkit.copyStream(in, out);
3077 if (null != optionAddStylesheet.getValue()) {
3078 File addStylesheetTargetFile = new File(resourcesDir,
3081 IOToolkit.copyFile(optionAddStylesheet.getValue(),
3082 addStylesheetTargetFile);
3085 if (null != optionStylesheetFile.getValue()) {
3086 File stylesheetTargetFile = new File(resourcesDir,
3089 IOToolkit.copyFile(optionStylesheetFile.getValue(),
3090 stylesheetTargetFile);
3093 // Write gjdoc.properties
3095 File gjdocPropertiesTargetFile = new File(getTargetDirectory(),
3096 "gjdoc.properties");
3097 writeGjdocProperties(gjdocPropertiesTargetFile);
3101 InputStream cssIn = getClass().getResourceAsStream("/htmldoclet/gjdochtml-vanilla.css");
3102 FileOutputStream cssOut = new FileOutputStream(stylesheetTargetFile);
3103 IOToolkit.copyStream(cssIn, cssOut);
3109 if (!optionNoDeprecatedList.getValue()) {
3110 printDeprecationPage();
3113 printSerializationPage();
3115 Collection packageDocsCollection = getAllPackages();
3116 PackageDoc[] packageDocs
3117 = (PackageDoc[])packageDocsCollection.toArray(new PackageDoc[0]);
3119 for (int i=0; i<packageDocs.length; ++i) {
3120 PackageDoc packageDoc = packageDocs[i];
3121 File packageDir = new File(getTargetDirectory(),
3122 packageDoc.name().replace('.', File.separatorChar));
3123 if (!packageDir.exists() && !packageDir.mkdirs()) {
3124 throw new IOException("Couldn't create directory " + packageDir);
3127 List packageSourceDirs = getPackageSourceDirs(packageDoc);
3128 Iterator pdIt = packageSourceDirs.iterator();
3129 while (pdIt.hasNext()) {
3130 File sourcePackageDir = (File)pdIt.next();
3131 copyDocFiles(sourcePackageDir, packageDir);
3134 catch (IOException ignore) {
3136 String pathToRoot = getPathToRoot(packageDir, getTargetDirectory());
3137 String packageName = packageDoc.name();
3138 if (0 == packageName.length()) {
3139 packageName = "<unnamed>";
3141 printNotice("Writing HTML files for package " + packageName);
3142 printPackagePage(packageDir, pathToRoot, packageDoc,
3143 (i > 0) ? packageDocs[i - 1] : null,
3144 (i < packageDocs.length - 1) ? packageDocs[i + 1] : null);
3145 if (!optionNoTree.getValue()) {
3146 printPackageTreePage(packageDir, pathToRoot, packageDoc);
3148 printPackageClassesMenuPage(packageDir, pathToRoot, packageDoc);
3149 ClassDoc[] classDocs = packageDoc.allClasses();
3150 for (int j=0; j<classDocs.length; ++j) {
3151 ClassDoc classDoc = classDocs[j];
3152 if (classDoc.isIncluded()) {
3153 printClassPage(packageDir, pathToRoot,
3155 (j > 0) ? classDocs[j - 1] : null,
3156 (j < classDocs.length - 1) ? classDocs[j + 1] : null
3158 if (optionUse.getValue()) {
3159 printClassUsagePage(packageDir, pathToRoot, classDocs[j]);
3161 if (optionLinkSource.getValue() && null == classDoc.containingClass()) {
3163 File sourceFile = getSourceFile(classDoc);
3165 Java2xhtml java2xhtml = new Java2xhtml();
3166 Properties properties = new Properties();
3167 properties.setProperty("isCodeSnippet", "true");
3168 properties.setProperty("hasLineNumbers", "true");
3169 java2xhtml.setProperties(properties);
3171 StringWriter sourceBuffer = new StringWriter();
3172 FileReader sourceReader = new FileReader(sourceFile);
3173 IOToolkit.copyStream(sourceReader, sourceBuffer);
3174 sourceReader.close();
3175 String result = java2xhtml.makeHTML(sourceBuffer.getBuffer(), sourceFile.getName());
3177 printSourcePage(packageDir,
3181 catch (IOException e) {
3182 printWarning("Cannot locate source file for class " + classDoc.qualifiedTypeName());
3190 private String getPathToRoot(File subDir, File rootDir)
3192 StringBuffer result = new StringBuffer();
3193 while (!subDir.equals(rootDir)) {
3194 if (result.length() > 0) {
3197 subDir = subDir.getParentFile();
3198 result.append("..");
3200 if (0 == result.length()) {
3203 return result.toString();
3206 private String getClassTypeName(ClassDoc classDoc)
3208 if (classDoc.isInterface()) {
3216 private String getClassTypeKeyword(ClassDoc classDoc)
3218 if (classDoc.isInterface()) {
3226 private String getMemberAnchor(ProgramElementDoc memberDoc)
3228 return getMemberAnchor(memberDoc, isJavadocCompatibleNames());
3231 private String getMemberAnchor(ProgramElementDoc memberDoc, boolean javadocCompatibility)
3233 StringBuffer anchor = new StringBuffer();
3234 anchor.append(memberDoc.name());
3235 if (memberDoc.isConstructor() || memberDoc.isMethod()) {
3236 if (javadocCompatibility) {
3237 anchor.append(((ExecutableMemberDoc)memberDoc).signature());
3241 Parameter[] parameters = ((ExecutableMemberDoc)memberDoc).parameters();
3242 for (int i=0; i<parameters.length; ++i) {
3243 anchor.append(parameters[i].type().typeName());
3244 for (int j=0; j<parameters[i].type().dimension().length()/2; ++j) {
3247 if (i < parameters.length - 1) {
3253 return anchor.toString();
3256 private String getFullModifiers(ProgramElementDoc memberDoc)
3258 StringBuffer result = new StringBuffer();
3259 if (memberDoc.isPackagePrivate()) {
3260 result.append("(package private) ");
3262 result.append(memberDoc.modifiers());
3263 if ((memberDoc.isClass() && ((ClassDoc)memberDoc).isAbstract())
3264 || (memberDoc.isMethod() && ((MethodDoc)memberDoc).isAbstract())) {
3265 result.append(" abstract");
3267 return result.toString();
3270 private String getSummaryModifiers(ProgramElementDoc memberDoc)
3272 StringBuffer result = new StringBuffer();
3273 if (memberDoc.isPackagePrivate()) {
3274 result.append("(package private) ");
3276 else if (memberDoc.isPrivate()) {
3277 result.append("private ");
3279 else if (memberDoc.isProtected()) {
3280 result.append("protected ");
3282 if (memberDoc.isStatic()) {
3283 result.append("static");
3285 else if ((memberDoc.isClass() && ((ClassDoc)memberDoc).isAbstract())
3286 || (memberDoc.isMethod() && ((MethodDoc)memberDoc).isAbstract())) {
3287 result.append("abstract");
3289 return result.toString();
3292 protected DocletOption[] getOptions()
3297 private DocletOptionFlag optionNoNavBar =
3298 new DocletOptionFlag("-nonavbar");
3300 private DocletOptionFlag optionNoTree =
3301 new DocletOptionFlag("-notree");
3303 private DocletOptionFlag optionNoDeprecatedList =
3304 new DocletOptionFlag("-nodeprecatedlist");
3306 private DocletOptionFlag optionNoIndex =
3307 new DocletOptionFlag("-noindex");
3309 private DocletOptionFlag optionUse =
3310 new DocletOptionFlag("-use");
3312 private DocletOptionFlag optionNoHelp =
3313 new DocletOptionFlag("-nohelp");
3315 private DocletOptionFlag optionNoComment =
3316 new DocletOptionFlag("-nocomment");
3318 private DocletOptionFlag optionSerialWarn =
3319 new DocletOptionFlag("-serialwarn");
3321 private DocletOptionFlag optionSplitIndex =
3322 new DocletOptionFlag("-splitindex");
3324 private DocletOptionString optionHeader =
3325 new DocletOptionString("-header");
3327 private DocletOptionString optionFooter =
3328 new DocletOptionString("-footer");
3330 private DocletOptionString optionBottom =
3331 new DocletOptionString("-bottom");
3333 private DocletOptionString optionWindowTitle =
3334 new DocletOptionString("-windowtitle");
3336 private DocletOptionString optionDocTitle =
3337 new DocletOptionString("-doctitle");
3339 private DocletOptionString optionTitle =
3340 new DocletOptionString("-title");
3342 private DocletOptionFile optionHelpFile =
3343 new DocletOptionFile("-helpfile");
3345 private DocletOptionFile optionStylesheetFile =
3346 new DocletOptionFile("-stylesheetfile");
3348 private DocletOptionFlag optionLinkSource =
3349 new DocletOptionFlag("-linksource");
3351 private DocletOption optionLink =
3352 new DocletOption("-link") {
3354 public int getLength()
3359 public boolean set(String[] optionArr)
3361 externalDocSets.add(new ExternalDocSet(optionArr[1], null));
3366 private DocletOption optionLinkOffline =
3367 new DocletOption("-linkoffline") {
3369 public int getLength()
3374 public boolean set(String[] optionArr)
3376 externalDocSets.add(new ExternalDocSet(optionArr[1], optionArr[2]));
3381 private DocletOptionString optionDocEncoding =
3382 new DocletOptionString("-docencoding");
3384 private DocletOptionString optionEncoding =
3385 new DocletOptionString("-encoding");
3387 private DocletOptionString optionCharset =
3388 new DocletOptionString("-charset");
3390 private DocletOptionFile optionAddStylesheet =
3391 new DocletOptionFile("-addstylesheet");
3393 private DocletOptionFlag optionValidHtml =
3394 new DocletOptionFlag("-validhtml");
3396 private DocletOptionString optionBaseUrl =
3397 new DocletOptionString("-baseurl");
3399 private DocletOption[] options =
3403 optionNoDeprecatedList,
3413 optionStylesheetFile,
3423 optionAddStylesheet,
3429 setInstance(new HtmlDoclet());
3432 private static String replaceDocRoot(HtmlPage output, String str)
3434 return StringToolkit.replace(str, "{@docRoot}", output.getPathToRoot());
3437 private String getOutputDocEncoding()
3439 String encoding = optionDocEncoding.getValue();
3441 if (null == encoding) {
3442 encoding = optionEncoding.getValue();
3448 private String getOutputCharset()
3450 if (null == outputCharset) {
3452 if (null != optionCharset.getValue()) {
3453 outputCharset = optionCharset.getValue();
3456 String fileEncoding = System.getProperty("file.encoding");
3457 if (null != fileEncoding) {
3459 outputCharset = Charset.forName(fileEncoding).name();
3461 catch (Exception ignore) {
3465 if (null == outputCharset) {
3466 printWarning("Cannot determine platform default charset, falling back to ISO-8859-1.");
3467 outputCharset = "ISO-8859-1";
3471 return outputCharset;
3474 public InlineTagRenderer getInlineTagRenderer()
3479 public String renderInlineTags(Tag[] tags, TagletContext context)
3481 StringBuffer result = new StringBuffer();
3483 HtmlRepairer repairer = new HtmlRepairer(getRootDoc(),
3488 for (int i=0; i<tags.length; ++i) {
3492 if ("Text".equals(tag.name())) {
3493 result.append(repairer.getWellformedHTML(tag.text()));
3495 else if ("@link".equals(tag.name())) {
3496 result.append(renderSeeTag((SeeTag)tag, context, false));
3498 else if ("@linkplain".equals(tag.name())) {
3499 result.append(renderSeeTag((SeeTag)tag, context, true));
3501 else if ("@docRoot".equals(tag.name())) {
3502 result.append(((HtmlTagletContext)context).getOutput().getPathToRoot());
3505 //TagletContext context = TagletContext.OVERVIEW; // FIXME
3506 Taglet taglet = (Taglet)tagletMap.get(tag.name().substring(1));
3507 if (null != taglet) {
3508 if (taglet instanceof GnuExtendedTaglet) {
3509 result.append(((GnuExtendedTaglet)taglet).toString(tag, context));
3512 result.append(taglet.toString(tag));
3517 result.append(repairer.terminateText());
3518 return result.toString();
3521 public String renderSeeTag(SeeTag seeTag, TagletContext context, boolean plainFont)
3523 StringBuffer result = new StringBuffer();
3526 String label = null;
3527 MemberDoc referencedMember = seeTag.referencedMember();
3528 if (null != seeTag.referencedClass()) {
3530 href = getClassDocURL(((HtmlTagletContext)context).getOutput(), seeTag.referencedClass());
3532 Doc doc = context.getDoc();
3533 ClassDoc classDoc = null;
3534 if (doc.isClass() || doc.isInterface()) {
3535 classDoc = (ClassDoc)doc;
3537 else if (doc.isField() || doc.isMethod() || doc.isConstructor()) {
3538 classDoc = ((MemberDoc)doc).containingClass();
3541 if (null == referencedMember
3542 || seeTag.referencedClass() != classDoc
3543 || ((HtmlTagletContext)context).isOnSerializedPage()) {
3545 if (!seeTag.referencedClass().isIncluded()) {
3546 label = possiblyQualifiedName(seeTag.referencedClass());
3549 label = seeTag.referencedClass().typeName();
3551 if (null != referencedMember) {
3559 if (null != referencedMember) {
3560 label += referencedMember.name();
3561 if (referencedMember.isMethod() || referencedMember.isConstructor()) {
3562 label += ((ExecutableMemberDoc)referencedMember).flatSignature();
3564 href += '#' + getMemberAnchor(referencedMember);
3566 else if (null != seeTag.referencedMemberName()) {
3571 String referencedClassName = seeTag.referencedClassName();
3573 if (null != referencedClassName) {
3575 String referencedPackageName = null;
3577 Iterator it = packageNameToDocSet.keySet().iterator();
3578 while (it.hasNext()) {
3579 String packageName = (String)it.next();
3580 if ((null == referencedPackageName
3581 || packageName.length() > referencedPackageName.length())
3582 && referencedClassName.startsWith(packageName + '.')) {
3583 referencedPackageName = packageName;
3587 if (null != referencedPackageName) {
3588 ExternalDocSet externalDocSet
3589 = (ExternalDocSet)packageNameToDocSet.get(referencedPackageName);
3591 String className = referencedClassName.substring(referencedPackageName.length() + 1);
3592 href = externalDocSet.getClassDocURL(referencedPackageName,
3596 String referencedMemberName = seeTag.referencedMemberName();
3598 if (null != referencedMemberName) {
3600 label += referencedMemberName;
3601 href += '#' + transformReferencedMemberName(referencedMemberName,
3602 externalDocSet.isJavadocCompatible());
3604 else if (null != seeTag.referencedMemberName()) {
3611 if (null != seeTag.label()
3612 && seeTag.label().length() > 0) {
3613 label = seeTag.label();
3616 if (null == label) {
3617 label = seeTag.text();
3618 if (label.startsWith("#")) {
3619 label = label.substring(1);
3622 label = label.replace('#', '.');
3628 result.append("<a href=\"");
3629 result.append(href);
3630 result.append("\">");
3632 result.append("<code>");
3634 result.append(label);
3636 result.append("</code>");
3638 result.append("</a>");
3642 result.append("<code>");
3644 result.append(label);
3646 result.append("</code>");
3650 return result.toString();
3653 protected String renderTag(String tagName, Tag[] tags, TagletContext context)
3655 Doc doc = context.getDoc();
3657 if ("see".equals(tagName)
3658 && ((tags.length > 0)
3660 && (((ClassDoc)doc).isSerializable()
3661 || ((ClassDoc)doc).isExternalizable())))) {
3663 StringBuffer result = new StringBuffer();
3664 result.append("<dl class=\"tag list\">");
3665 result.append("<dt class=\"tag section header\"><b>");
3666 result.append("See Also:");
3667 result.append("</b></dt>");
3669 boolean oneLine = true;
3672 result.append("<dd>");
3675 for (int i = 0; i < tags.length; ++i) {
3678 result.append(", ");
3682 result.append("<dd>");
3684 result.append(renderSeeTag((SeeTag)tags[i], context, false));
3686 result.append("</dd>");
3690 if ((doc instanceof ClassDoc)
3691 && (((ClassDoc)doc).isSerializable() || ((ClassDoc)doc).isExternalizable())) {
3692 if (tags.length > 0) {
3693 result.append(", ");
3695 HtmlPage output = ((HtmlTagletContext)context).getOutput();
3696 result.append("<a href=\"" + output.getPathToRoot() + "/serialized-form" + filenameExtension + "#" + ((ClassDoc)doc).qualifiedName() + "\">Serialized Form</a>");
3700 result.append("</dd>");
3702 result.append("</dl>");
3703 return result.toString();
3705 else if (tags.length > 0
3706 && "serial".equals(tagName)
3707 && ((HtmlTagletContext)context).isOnSerializedPage()) {
3709 return renderInlineTags(tags[0].inlineTags(), context);
3716 private String getWindowTitle()
3718 if (null == optionWindowTitle.getValue()) {
3719 return "Generated API Documentation";
3722 return optionWindowTitle.getValue();
3726 private String getPageTitle(String title)
3728 if (null == optionWindowTitle.getValue()) {
3732 return title + " (" + optionWindowTitle.getValue() + ")";
3736 protected String getDocletVersion()
3738 if (null == docletVersion) {
3739 docletVersion = gnu.classpath.Configuration.CLASSPATH_VERSION;
3741 return docletVersion;
3744 private Map getStylesheets()
3746 Map sheets = new HashMap();
3747 if (null != optionStylesheetFile.getValue()) {
3748 sheets.put("User-specified", new String[] {
3749 "resources/user.css"
3753 List cleanSheets = new LinkedList();
3754 cleanSheets.add("resources/gjdochtml-clean-layout.css");
3755 cleanSheets.add("resources/gjdochtml-clean-color1.css");
3756 if (null != optionAddStylesheet.getValue()) {
3757 cleanSheets.add("resources/user.css");
3759 sheets.put("GNU Clean", cleanSheets.toArray(new String[0]));
3764 protected boolean isSinglePackage()
3766 if (getRootDoc().firstSentenceTags().length > 0) {
3769 else if (null != optionDocTitle.getValue()
3770 || null != optionTitle.getValue()) {
3774 return super.isSinglePackage();
3778 private String getTypeParameters(ClassDoc classDoc)
3780 String parameters = "";
3781 TypeVariable[] params = classDoc.typeParameters();
3782 if (params != null && params.length > 0)
3784 parameters = "<";
3785 for (int a = 0; a < params.length; ++a)
3787 parameters += params[a].typeName();
3788 Type[] bounds = params[a].bounds();
3791 parameters += " extends ";
3792 for (int b = 0; a < bounds.length; ++b)
3794 parameters += bounds[a];
3795 if (b != bounds.length - 1)
3796 parameters += " & ";
3799 if (a != params.length - 1)
3802 parameters += ">";
3807 private String transformReferencedMemberName(String referencedMemberName,
3808 boolean javadocCompatibility)
3810 if (!javadocCompatibility) {
3811 StringBuffer result = new StringBuffer();
3812 for (int i=0; i<referencedMemberName.length(); ++i) {
3813 char c = referencedMemberName.charAt(i);
3815 case '(': result.append(':'); break;
3817 case ',': result.append(':'); break;
3818 case '[': result.append('-'); break;
3820 default: result.append(c); break;
3823 return result.toString();
3826 return referencedMemberName;
3830 public void writeGjdocProperties(File outputFile)
3833 Properties properties = new Properties();
3834 properties.setProperty("gjdoc.version", getDocletVersion());
3835 properties.setProperty("gjdoc.compat", Boolean.toString(isJavadocCompatibleNames()));
3837 FileOutputStream out = new FileOutputStream(outputFile);
3838 properties.store(out, "GNU Gjdoc API Documentation Set Descriptor");
3842 public boolean isJavadocCompatibleNames()
3844 return !optionValidHtml.getValue();
3847 private HtmlPage newHtmlPage(File file,
3851 return new HtmlPage(file,
3853 getOutputDocEncoding(),
3854 optionBaseUrl.getValue(),
3855 getTargetDirectory());
3858 private HtmlPage newHtmlPage(File file,
3863 return new HtmlPage(file,
3865 getOutputDocEncoding(),
3866 optionBaseUrl.getValue(),
3867 getTargetDirectory(),