001 /*
002 * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package com.sun.tools.doclets.formats.html;
027
028 import com.sun.tools.doclets.internal.toolkit.util.*;
029 import com.sun.javadoc.*;
030 import java.io.*;
031 import java.util.*;
032
033 /**
034 * Generate class usage information.
035 *
036 * @author Robert G. Field
037 */
038 public class ClassUseWriter extends SubWriterHolderWriter {
039
040 final ClassDoc classdoc;
041 Set<PackageDoc> pkgToPackageAnnotations = null;
042 final Map<String,List<ProgramElementDoc>> pkgToClassTypeParameter;
043 final Map<String,List<ProgramElementDoc>> pkgToClassAnnotations;
044 final Map<String,List<ProgramElementDoc>> pkgToMethodTypeParameter;
045 final Map<String,List<ProgramElementDoc>> pkgToMethodArgTypeParameter;
046 final Map<String,List<ProgramElementDoc>> pkgToMethodReturnTypeParameter;
047 final Map<String,List<ProgramElementDoc>> pkgToMethodAnnotations;
048 final Map<String,List<ProgramElementDoc>> pkgToMethodParameterAnnotations;
049 final Map<String,List<ProgramElementDoc>> pkgToFieldTypeParameter;
050 final Map<String,List<ProgramElementDoc>> pkgToFieldAnnotations;
051 final Map<String,List<ProgramElementDoc>> pkgToSubclass;
052 final Map<String,List<ProgramElementDoc>> pkgToSubinterface;
053 final Map<String,List<ProgramElementDoc>> pkgToImplementingClass;
054 final Map<String,List<ProgramElementDoc>> pkgToField;
055 final Map<String,List<ProgramElementDoc>> pkgToMethodReturn;
056 final Map<String,List<ProgramElementDoc>> pkgToMethodArgs;
057 final Map<String,List<ProgramElementDoc>> pkgToMethodThrows;
058 final Map<String,List<ProgramElementDoc>> pkgToConstructorAnnotations;
059 final Map<String,List<ProgramElementDoc>> pkgToConstructorParameterAnnotations;
060 final Map<String,List<ProgramElementDoc>> pkgToConstructorArgs;
061 final Map<String,List<ProgramElementDoc>> pkgToConstructorArgTypeParameter;
062 final Map<String,List<ProgramElementDoc>> pkgToConstructorThrows;
063 final SortedSet<PackageDoc> pkgSet;
064 final MethodWriterImpl methodSubWriter;
065 final ConstructorWriterImpl constrSubWriter;
066 final FieldWriterImpl fieldSubWriter;
067 final NestedClassWriterImpl classSubWriter;
068
069
070 /**
071 * Constructor.
072 *
073 * @param filename the file to be generated.
074 * @throws IOException
075 * @throws DocletAbortException
076 */
077 public ClassUseWriter(ConfigurationImpl configuration,
078 ClassUseMapper mapper, String path,
079 String filename, String relpath,
080 ClassDoc classdoc) throws IOException {
081 super(configuration, path, filename, relpath);
082 this.classdoc = classdoc;
083 if (mapper.classToPackageAnnotations.containsKey(classdoc.qualifiedName()))
084 pkgToPackageAnnotations = new HashSet<PackageDoc>(mapper.classToPackageAnnotations.get(classdoc.qualifiedName()));
085 configuration.currentcd = classdoc;
086 this.pkgSet = new TreeSet<PackageDoc>();
087 this.pkgToClassTypeParameter = pkgDivide(mapper.classToClassTypeParam);
088 this.pkgToClassAnnotations = pkgDivide(mapper.classToClassAnnotations);
089 this.pkgToMethodTypeParameter = pkgDivide(mapper.classToExecMemberDocTypeParam);
090 this.pkgToMethodArgTypeParameter = pkgDivide(mapper.classToExecMemberDocArgTypeParam);
091 this.pkgToFieldTypeParameter = pkgDivide(mapper.classToFieldDocTypeParam);
092 this.pkgToFieldAnnotations = pkgDivide(mapper.annotationToFieldDoc);
093 this.pkgToMethodReturnTypeParameter = pkgDivide(mapper.classToExecMemberDocReturnTypeParam);
094 this.pkgToMethodAnnotations = pkgDivide(mapper.classToExecMemberDocAnnotations);
095 this.pkgToMethodParameterAnnotations = pkgDivide(mapper.classToExecMemberDocParamAnnotation);
096 this.pkgToSubclass = pkgDivide(mapper.classToSubclass);
097 this.pkgToSubinterface = pkgDivide(mapper.classToSubinterface);
098 this.pkgToImplementingClass = pkgDivide(mapper.classToImplementingClass);
099 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 }
120
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 }
137
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 }
158
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 }
188
189 /**
190 * Print the class use list.
191 */
192 protected void generateClassUseFile() throws IOException {
193
194 printClassUseHeader();
195
196 if (pkgSet.size() > 0) {
197 generateClassUse();
198 } else {
199 printText("doclet.ClassUse_No.usage.of.0",
200 classdoc.qualifiedName());
201 p();
202 }
203
204 printClassUseFooter();
205 }
206
207 protected void generateClassUse() throws IOException {
208 if (configuration.packages.length > 1) {
209 generatePackageList();
210 generatePackageAnnotationList();
211 }
212 generateClassList();
213 }
214
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();
222
223 for (Iterator<PackageDoc> it = pkgSet.iterator(); it.hasNext();) {
224 PackageDoc pkg = it.next();
225 generatePackageUse(pkg);
226 }
227 tableEnd();
228 space();
229 p();
230 }
231
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<PackageDoc> it = pkgToPackageAnnotations.iterator(); it.hasNext();) {
244 PackageDoc pkg = 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 }
260
261 protected void generateClassList() throws IOException {
262 for (Iterator<PackageDoc> it = pkgSet.iterator(); it.hasNext();) {
263 PackageDoc pkg = 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 }
278
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 }
294
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));
305
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 }
381
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 }
401
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 }
411
412
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 }
422
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 }
432
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 }
443
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 }
455
456 }