Thu, 08 Jan 2009 16:26:59 -0800
6786028: Javadoc HTML WCAG 2.0 accessibility issues in standard doclet - Bold tags should be strong
Reviewed-by: jjg
1 /*
2 * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
26 package com.sun.tools.doclets.formats.html;
28 import com.sun.tools.doclets.internal.toolkit.util.*;
29 import com.sun.javadoc.*;
30 import java.io.*;
31 import java.util.*;
33 /**
34 * Generate class usage information.
35 *
36 * @author Robert G. Field
37 */
38 public class ClassUseWriter extends SubWriterHolderWriter {
40 final ClassDoc classdoc;
41 Set pkgToPackageAnnotations = null;
42 final Map<String,List<ProgramElementDoc>> pkgToClassTypeParameter;
43 final Map<String,List<ProgramElementDoc>> pkgToClassAnnotations;
44 final Map<String,List<ProgramElementDoc>> pkgToMethodTypeParameter;
45 final Map<String,List<ProgramElementDoc>> pkgToMethodArgTypeParameter;
46 final Map<String,List<ProgramElementDoc>> pkgToMethodReturnTypeParameter;
47 final Map<String,List<ProgramElementDoc>> pkgToMethodAnnotations;
48 final Map<String,List<ProgramElementDoc>> pkgToMethodParameterAnnotations;
49 final Map<String,List<ProgramElementDoc>> pkgToFieldTypeParameter;
50 final Map<String,List<ProgramElementDoc>> pkgToFieldAnnotations;
51 final Map<String,List<ProgramElementDoc>> pkgToSubclass;
52 final Map<String,List<ProgramElementDoc>> pkgToSubinterface;
53 final Map<String,List<ProgramElementDoc>> pkgToImplementingClass;
54 final Map<String,List<ProgramElementDoc>> pkgToField;
55 final Map<String,List<ProgramElementDoc>> pkgToMethodReturn;
56 final Map<String,List<ProgramElementDoc>> pkgToMethodArgs;
57 final Map<String,List<ProgramElementDoc>> pkgToMethodThrows;
58 final Map<String,List<ProgramElementDoc>> pkgToConstructorAnnotations;
59 final Map<String,List<ProgramElementDoc>> pkgToConstructorParameterAnnotations;
60 final Map<String,List<ProgramElementDoc>> pkgToConstructorArgs;
61 final Map<String,List<ProgramElementDoc>> pkgToConstructorArgTypeParameter;
62 final Map<String,List<ProgramElementDoc>> pkgToConstructorThrows;
63 final SortedSet<PackageDoc> pkgSet;
64 final MethodWriterImpl methodSubWriter;
65 final ConstructorWriterImpl constrSubWriter;
66 final FieldWriterImpl fieldSubWriter;
67 final NestedClassWriterImpl classSubWriter;
70 /**
71 * Constructor.
72 *
73 * @param filename the file to be generated.
74 * @throws IOException
75 * @throws DocletAbortException
76 */
77 public ClassUseWriter(ConfigurationImpl configuration,
78 ClassUseMapper mapper, String path,
79 String filename, String relpath,
80 ClassDoc classdoc) throws IOException {
81 super(configuration, path, filename, relpath);
82 this.classdoc = classdoc;
83 if (mapper.classToPackageAnnotations.containsKey(classdoc.qualifiedName()))
84 pkgToPackageAnnotations = new HashSet<PackageDoc>(mapper.classToPackageAnnotations.get(classdoc.qualifiedName()));
85 configuration.currentcd = classdoc;
86 this.pkgSet = new TreeSet<PackageDoc>();
87 this.pkgToClassTypeParameter = pkgDivide(mapper.classToClassTypeParam);
88 this.pkgToClassAnnotations = pkgDivide(mapper.classToClassAnnotations);
89 this.pkgToMethodTypeParameter = pkgDivide(mapper.classToExecMemberDocTypeParam);
90 this.pkgToMethodArgTypeParameter = pkgDivide(mapper.classToExecMemberDocArgTypeParam);
91 this.pkgToFieldTypeParameter = pkgDivide(mapper.classToFieldDocTypeParam);
92 this.pkgToFieldAnnotations = pkgDivide(mapper.annotationToFieldDoc);
93 this.pkgToMethodReturnTypeParameter = pkgDivide(mapper.classToExecMemberDocReturnTypeParam);
94 this.pkgToMethodAnnotations = pkgDivide(mapper.classToExecMemberDocAnnotations);
95 this.pkgToMethodParameterAnnotations = pkgDivide(mapper.classToExecMemberDocParamAnnotation);
96 this.pkgToSubclass = pkgDivide(mapper.classToSubclass);
97 this.pkgToSubinterface = pkgDivide(mapper.classToSubinterface);
98 this.pkgToImplementingClass = pkgDivide(mapper.classToImplementingClass);
99 this.pkgToField = pkgDivide(mapper.classToField);
100 this.pkgToMethodReturn = pkgDivide(mapper.classToMethodReturn);
101 this.pkgToMethodArgs = pkgDivide(mapper.classToMethodArgs);
102 this.pkgToMethodThrows = pkgDivide(mapper.classToMethodThrows);
103 this.pkgToConstructorAnnotations = pkgDivide(mapper.classToConstructorAnnotations);
104 this.pkgToConstructorParameterAnnotations = pkgDivide(mapper.classToConstructorParamAnnotation);
105 this.pkgToConstructorArgs = pkgDivide(mapper.classToConstructorArgs);
106 this.pkgToConstructorArgTypeParameter = pkgDivide(mapper.classToConstructorDocArgTypeParam);
107 this.pkgToConstructorThrows = pkgDivide(mapper.classToConstructorThrows);
108 //tmp test
109 if (pkgSet.size() > 0 &&
110 mapper.classToPackage.containsKey(classdoc.qualifiedName()) &&
111 !pkgSet.equals(mapper.classToPackage.get(classdoc.qualifiedName()))) {
112 configuration.root.printWarning("Internal error: package sets don't match: " + pkgSet + " with: " +
113 mapper.classToPackage.get(classdoc.qualifiedName()));
114 }
115 methodSubWriter = new MethodWriterImpl(this);
116 constrSubWriter = new ConstructorWriterImpl(this);
117 fieldSubWriter = new FieldWriterImpl(this);
118 classSubWriter = new NestedClassWriterImpl(this);
119 }
121 /**
122 * Write out class use pages.
123 * @throws DocletAbortException
124 */
125 public static void generate(ConfigurationImpl configuration,
126 ClassTree classtree) {
127 ClassUseMapper mapper = new ClassUseMapper(configuration.root, classtree);
128 ClassDoc[] classes = configuration.root.classes();
129 for (int i = 0; i < classes.length; i++) {
130 ClassUseWriter.generate(configuration, mapper, classes[i]);
131 }
132 PackageDoc[] pkgs = configuration.packages;
133 for (int i = 0; i < pkgs.length; i++) {
134 PackageUseWriter.generate(configuration, mapper, pkgs[i]);
135 }
136 }
138 private Map<String,List<ProgramElementDoc>> pkgDivide(Map<String,? extends List<? extends ProgramElementDoc>> classMap) {
139 Map<String,List<ProgramElementDoc>> map = new HashMap<String,List<ProgramElementDoc>>();
140 List<? extends ProgramElementDoc> list= classMap.get(classdoc.qualifiedName());
141 if (list != null) {
142 Collections.sort(list);
143 Iterator<? extends ProgramElementDoc> it = list.iterator();
144 while (it.hasNext()) {
145 ProgramElementDoc doc = it.next();
146 PackageDoc pkg = doc.containingPackage();
147 pkgSet.add(pkg);
148 List<ProgramElementDoc> inPkg = map.get(pkg.name());
149 if (inPkg == null) {
150 inPkg = new ArrayList<ProgramElementDoc>();
151 map.put(pkg.name(), inPkg);
152 }
153 inPkg.add(doc);
154 }
155 }
156 return map;
157 }
159 /**
160 * Generate a class page.
161 */
162 public static void generate(ConfigurationImpl configuration,
163 ClassUseMapper mapper, ClassDoc classdoc) {
164 ClassUseWriter clsgen;
165 String path = DirectoryManager.getDirectoryPath(classdoc.
166 containingPackage());
167 if (path.length() > 0) {
168 path += File.separator;
169 }
170 path += "class-use";
171 String filename = classdoc.name() + ".html";
172 String pkgname = classdoc.containingPackage().name();
173 pkgname += (pkgname.length() > 0)? ".class-use": "class-use";
174 String relpath = DirectoryManager.getRelativePath(pkgname);
175 try {
176 clsgen = new ClassUseWriter(configuration,
177 mapper, path, filename,
178 relpath, classdoc);
179 clsgen.generateClassUseFile();
180 clsgen.close();
181 } catch (IOException exc) {
182 configuration.standardmessage.
183 error("doclet.exception_encountered",
184 exc.toString(), filename);
185 throw new DocletAbortException();
186 }
187 }
189 /**
190 * Print the class use list.
191 */
192 protected void generateClassUseFile() throws IOException {
194 printClassUseHeader();
196 if (pkgSet.size() > 0) {
197 generateClassUse();
198 } else {
199 printText("doclet.ClassUse_No.usage.of.0",
200 classdoc.qualifiedName());
201 p();
202 }
204 printClassUseFooter();
205 }
207 protected void generateClassUse() throws IOException {
208 if (configuration.packages.length > 1) {
209 generatePackageList();
210 generatePackageAnnotationList();
211 }
212 generateClassList();
213 }
215 protected void generatePackageList() throws IOException {
216 tableIndexSummary();
217 tableHeaderStart("#CCCCFF");
218 printText("doclet.ClassUse_Packages.that.use.0",
219 getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc,
220 false)));
221 tableHeaderEnd();
223 for (Iterator it = pkgSet.iterator(); it.hasNext();) {
224 PackageDoc pkg = (PackageDoc)it.next();
225 generatePackageUse(pkg);
226 }
227 tableEnd();
228 space();
229 p();
230 }
232 protected void generatePackageAnnotationList() throws IOException {
233 if ((! classdoc.isAnnotationType()) ||
234 pkgToPackageAnnotations == null ||
235 pkgToPackageAnnotations.size() == 0)
236 return;
237 tableIndexSummary();
238 tableHeaderStart("#CCCCFF");
239 printText("doclet.ClassUse_PackageAnnotation",
240 getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc,
241 false)));
242 tableHeaderEnd();
243 for (Iterator it = pkgToPackageAnnotations.iterator(); it.hasNext();) {
244 PackageDoc pkg = (PackageDoc)it.next();
245 trBgcolorStyle("white", "TableRowColor");
246 summaryRow(0);
247 //Just want an anchor here.
248 printPackageLink(pkg, pkg.name(), true);
249 summaryRowEnd();
250 summaryRow(0);
251 printSummaryComment(pkg);
252 space();
253 summaryRowEnd();
254 trEnd();
255 }
256 tableEnd();
257 space();
258 p();
259 }
261 protected void generateClassList() throws IOException {
262 for (Iterator it = pkgSet.iterator(); it.hasNext();) {
263 PackageDoc pkg = (PackageDoc)it.next();
264 anchor(pkg.name());
265 tableIndexSummary();
266 tableHeaderStart("#CCCCFF");
267 printText("doclet.ClassUse_Uses.of.0.in.1",
268 getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER,
269 classdoc, false)),
270 getPackageLink(pkg, Util.getPackageName(pkg), false));
271 tableHeaderEnd();
272 tableEnd();
273 space();
274 p();
275 generateClassUse(pkg);
276 }
277 }
279 /**
280 * Print the package use list.
281 */
282 protected void generatePackageUse(PackageDoc pkg) throws IOException {
283 trBgcolorStyle("white", "TableRowColor");
284 summaryRow(0);
285 //Just want an anchor here.
286 printHyperLink("", pkg.name(), Util.getPackageName(pkg), true);
287 summaryRowEnd();
288 summaryRow(0);
289 printSummaryComment(pkg);
290 space();
291 summaryRowEnd();
292 trEnd();
293 }
295 /**
296 * Print the class use list.
297 */
298 protected void generateClassUse(PackageDoc pkg) throws IOException {
299 String classLink = getLink(new LinkInfoImpl(
300 LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc, false));
301 String pkgLink = getPackageLink(pkg, Util.getPackageName(pkg), false);
302 classSubWriter.printUseInfo(pkgToClassAnnotations.get(pkg.name()),
303 configuration.getText("doclet.ClassUse_Annotation", classLink,
304 pkgLink));
306 classSubWriter.printUseInfo(pkgToClassTypeParameter.get(pkg.name()),
307 configuration.getText("doclet.ClassUse_TypeParameter", classLink,
308 pkgLink));
309 classSubWriter.printUseInfo(pkgToSubclass.get(pkg.name()),
310 configuration.getText("doclet.ClassUse_Subclass", classLink,
311 pkgLink));
312 classSubWriter.printUseInfo(pkgToSubinterface.get(pkg.name()),
313 configuration.getText("doclet.ClassUse_Subinterface",
314 classLink,
315 pkgLink));
316 classSubWriter.printUseInfo(pkgToImplementingClass.get(pkg.name()),
317 configuration.getText("doclet.ClassUse_ImplementingClass",
318 classLink,
319 pkgLink));
320 fieldSubWriter.printUseInfo(pkgToField.get(pkg.name()),
321 configuration.getText("doclet.ClassUse_Field",
322 classLink,
323 pkgLink));
324 fieldSubWriter.printUseInfo(pkgToFieldAnnotations.get(pkg.name()),
325 configuration.getText("doclet.ClassUse_FieldAnnotations",
326 classLink,
327 pkgLink));
328 fieldSubWriter.printUseInfo(pkgToFieldTypeParameter.get(pkg.name()),
329 configuration.getText("doclet.ClassUse_FieldTypeParameter",
330 classLink,
331 pkgLink));
332 methodSubWriter.printUseInfo(pkgToMethodAnnotations.get(pkg.name()),
333 configuration.getText("doclet.ClassUse_MethodAnnotations", classLink,
334 pkgLink));
335 methodSubWriter.printUseInfo(pkgToMethodParameterAnnotations.get(pkg.name()),
336 configuration.getText("doclet.ClassUse_MethodParameterAnnotations", classLink,
337 pkgLink));
338 methodSubWriter.printUseInfo(pkgToMethodTypeParameter.get(pkg.name()),
339 configuration.getText("doclet.ClassUse_MethodTypeParameter", classLink,
340 pkgLink));
341 methodSubWriter.printUseInfo(pkgToMethodReturn.get(pkg.name()),
342 configuration.getText("doclet.ClassUse_MethodReturn",
343 classLink,
344 pkgLink));
345 methodSubWriter.printUseInfo(pkgToMethodReturnTypeParameter.get(pkg.name()),
346 configuration.getText("doclet.ClassUse_MethodReturnTypeParameter", classLink,
347 pkgLink));
348 methodSubWriter.printUseInfo(pkgToMethodArgs.get(pkg.name()),
349 configuration.getText("doclet.ClassUse_MethodArgs",
350 classLink,
351 pkgLink));
352 methodSubWriter.printUseInfo(pkgToMethodArgTypeParameter.get(pkg.name()),
353 configuration.getText("doclet.ClassUse_MethodArgsTypeParameters",
354 classLink,
355 pkgLink));
356 methodSubWriter.printUseInfo(pkgToMethodThrows.get(pkg.name()),
357 configuration.getText("doclet.ClassUse_MethodThrows",
358 classLink,
359 pkgLink));
360 constrSubWriter.printUseInfo(pkgToConstructorAnnotations.get(pkg.name()),
361 configuration.getText("doclet.ClassUse_ConstructorAnnotations",
362 classLink,
363 pkgLink));
364 constrSubWriter.printUseInfo(pkgToConstructorParameterAnnotations.get(pkg.name()),
365 configuration.getText("doclet.ClassUse_ConstructorParameterAnnotations",
366 classLink,
367 pkgLink));
368 constrSubWriter.printUseInfo(pkgToConstructorArgs.get(pkg.name()),
369 configuration.getText("doclet.ClassUse_ConstructorArgs",
370 classLink,
371 pkgLink));
372 constrSubWriter.printUseInfo(pkgToConstructorArgTypeParameter.get(pkg.name()),
373 configuration.getText("doclet.ClassUse_ConstructorArgsTypeParameters",
374 classLink,
375 pkgLink));
376 constrSubWriter.printUseInfo(pkgToConstructorThrows.get(pkg.name()),
377 configuration.getText("doclet.ClassUse_ConstructorThrows",
378 classLink,
379 pkgLink));
380 }
382 /**
383 * Print the header for the class use Listing.
384 */
385 protected void printClassUseHeader() {
386 String cltype = configuration.getText(classdoc.isInterface()?
387 "doclet.Interface":
388 "doclet.Class");
389 String clname = classdoc.qualifiedName();
390 printHtmlHeader(configuration.getText("doclet.Window_ClassUse_Header",
391 cltype, clname), null, true);
392 printTop();
393 navLinks(true);
394 hr();
395 center();
396 h2();
397 strongText("doclet.ClassUse_Title", cltype, clname);
398 h2End();
399 centerEnd();
400 }
402 /**
403 * Print the footer for the class use Listing.
404 */
405 protected void printClassUseFooter() {
406 hr();
407 navLinks(false);
408 printBottom();
409 printBodyHtmlEnd();
410 }
413 /**
414 * Print this package link
415 */
416 protected void navLinkPackage() {
417 navCellStart();
418 printHyperLink("../package-summary.html", "",
419 configuration.getText("doclet.Package"), true, "NavBarFont1");
420 navCellEnd();
421 }
423 /**
424 * Print class page indicator
425 */
426 protected void navLinkClass() {
427 navCellStart();
428 printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc, "",
429 configuration.getText("doclet.Class"), true, "NavBarFont1"));
430 navCellEnd();
431 }
433 /**
434 * Print class use link
435 */
436 protected void navLinkClassUse() {
437 navCellRevStart();
438 fontStyle("NavBarFont1Rev");
439 strongText("doclet.navClassUse");
440 fontEnd();
441 navCellEnd();
442 }
444 protected void navLinkTree() {
445 navCellStart();
446 if (classdoc.containingPackage().isIncluded()) {
447 printHyperLink("../package-tree.html", "",
448 configuration.getText("doclet.Tree"), true, "NavBarFont1");
449 } else {
450 printHyperLink(relativePath + "overview-tree.html", "",
451 configuration.getText("doclet.Tree"), true, "NavBarFont1");
452 }
453 navCellEnd();
454 }
456 }