001: /*
002: * Copyright 1997-2005 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.*;
029: import com.sun.tools.doclets.internal.toolkit.util.*;
030: import com.sun.tools.doclets.internal.toolkit.builders.*;
031: import com.sun.javadoc.*;
032:
033: import java.util.*;
034: import com.sun.tools.doclets.internal.toolkit.taglets.*;
035:
036: /**
037: * Generate the Class Information Page.
038: * @see com.sun.javadoc.ClassDoc
039: * @see java.util.Collections
040: * @see java.util.List
041: * @see java.util.ArrayList
042: * @see java.util.HashMap
043: *
044: * @author Atul M Dambalkar
045: * @author Robert Field
046: */
047: public class ClassWriterImpl extends SubWriterHolderWriter implements
048: ClassWriter {
049:
050: protected ClassDoc classDoc;
051:
052: protected ClassTree classtree;
053:
054: protected ClassDoc prev;
055:
056: protected ClassDoc next;
057:
058: /**
059: * @param classDoc the class being documented.
060: * @param prevClass the previous class that was documented.
061: * @param nextClass the next class being documented.
062: * @param classTree the class tree for the given class.
063: */
064: public ClassWriterImpl(ClassDoc classDoc, ClassDoc prevClass,
065: ClassDoc nextClass, ClassTree classTree) throws Exception {
066: super (ConfigurationImpl.getInstance(), DirectoryManager
067: .getDirectoryPath(classDoc.containingPackage()),
068: classDoc.name() + ".html", DirectoryManager
069: .getRelativePath(classDoc.containingPackage()
070: .name()));
071: this .classDoc = classDoc;
072: configuration.currentcd = classDoc;
073: this .classtree = classTree;
074: this .prev = prevClass;
075: this .next = nextClass;
076: }
077:
078: /**
079: * Print this package link
080: */
081: protected void navLinkPackage() {
082: navCellStart();
083: printHyperLink("package-summary.html", "", configuration
084: .getText("doclet.Package"), true, "NavBarFont1");
085: navCellEnd();
086: }
087:
088: /**
089: * Print class page indicator
090: */
091: protected void navLinkClass() {
092: navCellRevStart();
093: fontStyle("NavBarFont1Rev");
094: boldText("doclet.Class");
095: fontEnd();
096: navCellEnd();
097: }
098:
099: /**
100: * Print class use link
101: */
102: protected void navLinkClassUse() {
103: navCellStart();
104: printHyperLink("class-use/" + filename, "", configuration
105: .getText("doclet.navClassUse"), true, "NavBarFont1");
106: navCellEnd();
107: }
108:
109: /**
110: * Print previous package link
111: */
112: protected void navLinkPrevious() {
113: if (prev == null) {
114: printText("doclet.Prev_Class");
115: } else {
116: printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS,
117: prev, "", configuration
118: .getText("doclet.Prev_Class"), true));
119: }
120: }
121:
122: /**
123: * Print next package link
124: */
125: protected void navLinkNext() {
126: if (next == null) {
127: printText("doclet.Next_Class");
128: } else {
129: printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS,
130: next, "", configuration
131: .getText("doclet.Next_Class"), true));
132: }
133: }
134:
135: /**
136: * {@inheritDoc}
137: */
138: public void writeHeader(String header) {
139: String pkgname = (classDoc.containingPackage() != null) ? classDoc
140: .containingPackage().name()
141: : "";
142: String clname = classDoc.name();
143: printHtmlHeader(clname, configuration.metakeywords
144: .getMetaKeywords(classDoc), true);
145: printTop();
146: navLinks(true);
147: hr();
148: println("<!-- ======== START OF CLASS DATA ======== -->");
149: h2();
150: if (pkgname.length() > 0) {
151: font("-1");
152: print(pkgname);
153: fontEnd();
154: br();
155: }
156: LinkInfoImpl linkInfo = new LinkInfoImpl(
157: LinkInfoImpl.CONTEXT_CLASS_HEADER, classDoc, false);
158: //Let's not link to ourselves in the header.
159: linkInfo.linkToSelf = false;
160: print(header + getTypeParameterLinks(linkInfo));
161: h2End();
162: }
163:
164: /**
165: * {@inheritDoc}
166: */
167: public void writeFooter() {
168: println("<!-- ========= END OF CLASS DATA ========= -->");
169: hr();
170: navLinks(false);
171: printBottom();
172: printBodyHtmlEnd();
173: }
174:
175: /**
176: * {@inheritDoc}
177: */
178: public void writeClassSignature(String modifiers) {
179: boolean isInterface = classDoc.isInterface();
180: dl();
181: dt();
182: preNoNewLine();
183: writeAnnotationInfo(classDoc);
184: print(modifiers);
185: LinkInfoImpl linkInfo = new LinkInfoImpl(
186: LinkInfoImpl.CONTEXT_CLASS_SIGNATURE, classDoc, false);
187: //Let's not link to ourselves in the signature.
188: linkInfo.linkToSelf = false;
189: String name = classDoc.name() + getTypeParameterLinks(linkInfo);
190: if (configuration().linksource) {
191: printSrcLink(classDoc, name);
192: } else {
193: bold(name);
194: }
195: if (!isInterface) {
196: Type super class = Util.getFirstVisibleSuperClass(classDoc,
197: configuration());
198: if (super class != null) {
199: dt();
200: print("extends ");
201: printLink(new LinkInfoImpl(
202: LinkInfoImpl.CONTEXT_CLASS_SIGNATURE_PARENT_NAME,
203: super class));
204: }
205: }
206: Type[] implIntfacs = classDoc.interfaceTypes();
207: if (implIntfacs != null && implIntfacs.length > 0) {
208: int counter = 0;
209: for (int i = 0; i < implIntfacs.length; i++) {
210: ClassDoc classDoc = implIntfacs[i].asClassDoc();
211: if (!(classDoc.isPublic() || Util.isLinkable(classDoc,
212: configuration()))) {
213: continue;
214: }
215: if (counter == 0) {
216: dt();
217: print(isInterface ? "extends " : "implements ");
218: } else {
219: print(", ");
220: }
221: printLink(new LinkInfoImpl(
222: LinkInfoImpl.CONTEXT_CLASS_SIGNATURE_PARENT_NAME,
223: implIntfacs[i]));
224: counter++;
225: }
226: }
227: dlEnd();
228: preEnd();
229: p();
230: }
231:
232: /**
233: * {@inheritDoc}
234: */
235: public void writeClassDescription() {
236: if (!configuration.nocomment) {
237: // generate documentation for the class.
238: if (classDoc.inlineTags().length > 0) {
239: printInlineComment(classDoc);
240: p();
241: }
242: }
243: }
244:
245: /**
246: * {@inheritDoc}
247: */
248: public void writeClassTagInfo() {
249: if (!configuration.nocomment) {
250: // Print Information about all the tags here
251: printTags(classDoc);
252: hr();
253: p();
254: } else {
255: hr();
256: }
257: }
258:
259: /**
260: * {@inheritDoc}
261: */
262: public void writeClassDeprecationInfo() {
263: hr();
264: Tag[] deprs = classDoc.tags("deprecated");
265: if (Util.isDeprecated(classDoc)) {
266: boldText("doclet.Deprecated");
267: if (deprs.length > 0) {
268: Tag[] commentTags = deprs[0].inlineTags();
269: if (commentTags.length > 0) {
270: space();
271: printInlineDeprecatedComment(classDoc, deprs[0]);
272: }
273: }
274: p();
275: }
276: }
277:
278: /**
279: * Generate the indent and get the line image for the class tree.
280: * For user accessibility, the image includes the alt attribute
281: * "extended by". (This method is not intended for a class
282: * implementing an interface, where "implemented by" would be required.)
283: *
284: * indent integer indicating the number of spaces to indent
285: */
286: private void writeStep(int indent) {
287: print(spaces(4 * indent - 2));
288: print("<IMG SRC=\"" + relativepathNoSlash
289: + "/resources/inherit.gif\" " + "ALT=\""
290: + configuration.getText("doclet.extended_by") + " \">");
291: }
292:
293: /**
294: * Print the class hierarchy tree for the given class.
295: * @param type the class to print the hierarchy for.
296: * @return return the amount that should be indented in
297: * the next level of the tree.
298: */
299: private int writeTreeForClassHelper(Type type) {
300: Type sup = Util.getFirstVisibleSuperClass(
301: type instanceof ClassDoc ? (ClassDoc) type : type
302: .asClassDoc(), configuration());
303: int indent = 0;
304: if (sup != null) {
305: indent = writeTreeForClassHelper(sup);
306: writeStep(indent);
307: }
308:
309: if (type.equals(classDoc)) {
310: String typeParameters = getTypeParameterLinks(new LinkInfoImpl(
311: LinkInfoImpl.CONTEXT_TREE, classDoc, false));
312: if (configuration.shouldExcludeQualifier(classDoc
313: .containingPackage().name())) {
314: bold(type.asClassDoc().name() + typeParameters);
315: } else {
316: bold(type.asClassDoc().qualifiedName() + typeParameters);
317: }
318: } else {
319: print(getLink(new LinkInfoImpl(
320: LinkInfoImpl.CONTEXT_CLASS_TREE_PARENT,
321: type instanceof ClassDoc ? (ClassDoc) type : type,
322: configuration.getClassName(type.asClassDoc()),
323: false)));
324: }
325: println();
326: return indent + 1;
327: }
328:
329: /**
330: * Print the class hierarchy tree for this class only.
331: */
332: public void writeClassTree() {
333: if (!classDoc.isClass()) {
334: return;
335: }
336: pre();
337: writeTreeForClassHelper(classDoc);
338: preEnd();
339: }
340:
341: /**
342: * Write the type parameter information.
343: */
344: public void writeTypeParamInfo() {
345: if (classDoc.typeParamTags().length > 0) {
346: dl();
347: dt();
348: TagletOutput output = (new ParamTaglet()).getTagletOutput(
349: classDoc, getTagletWriterInstance(false));
350: print(output.toString());
351: dlEnd();
352: }
353: }
354:
355: /**
356: * {@inheritDoc}
357: */
358: public void writeSubClassInfo() {
359: if (classDoc.isClass()) {
360: if (classDoc.qualifiedName().equals("java.lang.Object")
361: || classDoc.qualifiedName().equals(
362: "org.omg.CORBA.Object")) {
363: return; // Don't generate the list, too huge
364: }
365: List subclasses = classtree.subs(classDoc, false);
366: if (subclasses.size() > 0) {
367: dl();
368: dt();
369: boldText("doclet.Subclasses");
370: writeClassLinks(LinkInfoImpl.CONTEXT_SUBCLASSES,
371: subclasses);
372: }
373: }
374: }
375:
376: /**
377: * {@inheritDoc}
378: */
379: public void writeSubInterfacesInfo() {
380: if (classDoc.isInterface()) {
381: List subInterfaces = classtree.allSubs(classDoc, false);
382: if (subInterfaces.size() > 0) {
383: dl();
384: dt();
385: boldText("doclet.Subinterfaces");
386: writeClassLinks(LinkInfoImpl.CONTEXT_SUBINTERFACES,
387: subInterfaces);
388: }
389: }
390: }
391:
392: /**
393: * If this is the interface which are the classes, that implement this?
394: */
395: public void writeInterfaceUsageInfo() {
396: if (!classDoc.isInterface()) {
397: return;
398: }
399: if (classDoc.qualifiedName().equals("java.lang.Cloneable")
400: || classDoc.qualifiedName().equals(
401: "java.io.Serializable")) {
402: return; // Don't generate the list, too big
403: }
404: List implcl = classtree.implementingclasses(classDoc);
405: if (implcl.size() > 0) {
406: dl();
407: dt();
408: boldText("doclet.Implementing_Classes");
409: writeClassLinks(LinkInfoImpl.CONTEXT_IMPLEMENTED_CLASSES,
410: implcl);
411: }
412: }
413:
414: /**
415: * {@inheritDoc}
416: */
417: public void writeImplementedInterfacesInfo() {
418: //NOTE: we really should be using ClassDoc.interfaceTypes() here, but
419: // it doesn't walk up the tree like we want it to.
420: List interfaceArray = Util.getAllInterfaces(classDoc,
421: configuration);
422: if (classDoc.isClass() && interfaceArray.size() > 0) {
423: dl();
424: dt();
425: boldText("doclet.All_Implemented_Interfaces");
426: writeClassLinks(
427: LinkInfoImpl.CONTEXT_IMPLEMENTED_INTERFACES,
428: interfaceArray);
429: }
430: }
431:
432: /**
433: * {@inheritDoc}
434: */
435: public void writeSuperInterfacesInfo() {
436: //NOTE: we really should be using ClassDoc.interfaceTypes() here, but
437: // it doesn't walk up the tree like we want it to.
438: List interfaceArray = Util.getAllInterfaces(classDoc,
439: configuration);
440: if (classDoc.isInterface() && interfaceArray.size() > 0) {
441: dl();
442: dt();
443: boldText("doclet.All_Superinterfaces");
444: writeClassLinks(LinkInfoImpl.CONTEXT_SUPER_INTERFACES,
445: interfaceArray);
446: }
447: }
448:
449: /**
450: * Generate links to the given classes.
451: */
452: private void writeClassLinks(int context, List list) {
453: Object[] typeList = list.toArray();
454: //Sort the list to be printed.
455: print(' ');
456: dd();
457: for (int i = 0; i < list.size(); i++) {
458: if (i > 0) {
459: print(", ");
460: }
461: if (typeList[i] instanceof ClassDoc) {
462: printLink(new LinkInfoImpl(context,
463: (ClassDoc) (typeList[i])));
464:
465: } else {
466: printLink(new LinkInfoImpl(context,
467: (Type) (typeList[i])));
468: }
469: }
470: ddEnd();
471: dlEnd();
472: }
473:
474: protected void navLinkTree() {
475: navCellStart();
476: printHyperLink("package-tree.html", "", configuration
477: .getText("doclet.Tree"), true, "NavBarFont1");
478: navCellEnd();
479: }
480:
481: protected void printSummaryDetailLinks() {
482: try {
483: tr();
484: tdVAlignClass("top", "NavBarCell3");
485: font("-2");
486: print(" ");
487: navSummaryLinks();
488: fontEnd();
489: tdEnd();
490: tdVAlignClass("top", "NavBarCell3");
491: font("-2");
492: navDetailLinks();
493: fontEnd();
494: tdEnd();
495: trEnd();
496: } catch (Exception e) {
497: e.printStackTrace();
498: throw new DocletAbortException();
499: }
500: }
501:
502: protected void navSummaryLinks() throws Exception {
503: printText("doclet.Summary");
504: space();
505: MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder) configuration
506: .getBuilderFactory().getMemberSummaryBuilder(this );
507: String[] navLinkLabels = new String[] { "doclet.navNested",
508: "doclet.navEnum", "doclet.navField",
509: "doclet.navConstructor", "doclet.navMethod" };
510: for (int i = 0; i < navLinkLabels.length; i++) {
511: if (i == VisibleMemberMap.ENUM_CONSTANTS
512: && !classDoc.isEnum()) {
513: continue;
514: }
515: if (i == VisibleMemberMap.CONSTRUCTORS && classDoc.isEnum()) {
516: continue;
517: }
518: AbstractMemberWriter writer = ((AbstractMemberWriter) memberSummaryBuilder
519: .getMemberSummaryWriter(i));
520: if (writer == null) {
521: printText(navLinkLabels[i]);
522: } else {
523: writer.navSummaryLink(memberSummaryBuilder.members(i),
524: memberSummaryBuilder.getVisibleMemberMap(i));
525: }
526: if (i < navLinkLabels.length - 1) {
527: navGap();
528: }
529: }
530: }
531:
532: /**
533: * Method navDetailLinks
534: *
535: * @throws Exception
536: *
537: */
538: protected void navDetailLinks() throws Exception {
539: printText("doclet.Detail");
540: space();
541: MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder) configuration
542: .getBuilderFactory().getMemberSummaryBuilder(this );
543: String[] navLinkLabels = new String[] { "doclet.navNested",
544: "doclet.navEnum", "doclet.navField",
545: "doclet.navConstructor", "doclet.navMethod" };
546: for (int i = 1; i < navLinkLabels.length; i++) {
547: AbstractMemberWriter writer = ((AbstractMemberWriter) memberSummaryBuilder
548: .getMemberSummaryWriter(i));
549: if (i == VisibleMemberMap.ENUM_CONSTANTS
550: && !classDoc.isEnum()) {
551: continue;
552: }
553: if (i == VisibleMemberMap.CONSTRUCTORS && classDoc.isEnum()) {
554: continue;
555: }
556: if (writer == null) {
557: printText(navLinkLabels[i]);
558: } else {
559: writer.navDetailLink(memberSummaryBuilder.members(i));
560: }
561: if (i < navLinkLabels.length - 1) {
562: navGap();
563: }
564: }
565: }
566:
567: protected void navGap() {
568: space();
569: print('|');
570: space();
571: }
572:
573: /**
574: * If this is an inner class or interface, write the enclosing class or
575: * interface.
576: */
577: public void writeNestedClassInfo() {
578: ClassDoc outerClass = classDoc.containingClass();
579: if (outerClass != null) {
580: dl();
581: dt();
582: if (outerClass.isInterface()) {
583: boldText("doclet.Enclosing_Interface");
584: } else {
585: boldText("doclet.Enclosing_Class");
586: }
587: dd();
588: printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS,
589: outerClass, false));
590: ddEnd();
591: dlEnd();
592: }
593: }
594:
595: /**
596: * Return the classDoc being documented.
597: *
598: * @return the classDoc being documented.
599: */
600: public ClassDoc getClassDoc() {
601: return classDoc;
602: }
603:
604: /**
605: * {@inheritDoc}
606: */
607: public void completeMemberSummaryBuild() {
608: p();
609: }
610: }
|