ClassWriterImpl.java revision 3593:70c752a3447a
1/*
2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. 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.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package jdk.javadoc.internal.doclets.formats.html;
27
28import java.io.IOException;
29import java.util.*;
30
31import javax.lang.model.element.AnnotationMirror;
32import javax.lang.model.element.Element;
33import javax.lang.model.element.ModuleElement;
34import javax.lang.model.element.PackageElement;
35import javax.lang.model.element.TypeElement;
36import javax.lang.model.type.TypeMirror;
37import javax.lang.model.util.SimpleElementVisitor8;
38
39import com.sun.source.doctree.DocTree;
40import com.sun.tools.javac.util.DefinedBy;
41import com.sun.tools.javac.util.DefinedBy.Api;
42import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
43import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
44import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
45import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
46import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
47import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
48import jdk.javadoc.internal.doclets.toolkit.Content;
49import jdk.javadoc.internal.doclets.toolkit.builders.MemberSummaryBuilder;
50import jdk.javadoc.internal.doclets.toolkit.taglets.ParamTaglet;
51import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
52import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
53import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
54import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
55import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException;
56import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
57import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
58import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind;
59
60/**
61 * Generate the Class Information Page.
62 *
63 *  <p><b>This is NOT part of any supported API.
64 *  If you write code that depends on this, you do so at your own risk.
65 *  This code and its internal interfaces are subject to change or
66 *  deletion without notice.</b>
67 *
68 * @see javax.lang.model.element.TypeElement
69 * @see java.util.Collections
70 * @see java.util.List
71 * @see java.util.ArrayList
72 * @see java.util.HashMap
73 *
74 * @author Atul M Dambalkar
75 * @author Robert Field
76 * @author Bhavesh Patel (Modified)
77 */
78public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWriter {
79
80    protected final TypeElement typeElement;
81
82    protected final ClassTree classtree;
83
84    protected final TypeElement prev;
85
86    protected final TypeElement next;
87
88    /**
89     * @param configuration the configuration data for the doclet
90     * @param typeElement the class being documented.
91     * @param prevClass the previous class that was documented.
92     * @param nextClass the next class being documented.
93     * @param classTree the class tree for the given class.
94     * @throws java.io.IOException
95     */
96    public ClassWriterImpl(ConfigurationImpl configuration, TypeElement typeElement,
97            TypeElement prevClass, TypeElement nextClass, ClassTree classTree)
98            throws IOException {
99        super(configuration, DocPath.forClass(configuration.utils, typeElement));
100        this.typeElement = typeElement;
101        configuration.currentTypeElement = typeElement;
102        this.classtree = classTree;
103        this.prev = prevClass;
104        this.next = nextClass;
105    }
106
107    /**
108     * Get the module link.
109     *
110     * @return a content tree for the module link
111     */
112    @Override
113    protected Content getNavLinkModule() {
114        Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(typeElement),
115                contents.moduleLabel);
116        Content li = HtmlTree.LI(linkContent);
117        return li;
118    }
119
120    /**
121     * Get this package link.
122     *
123     * @return a content tree for the package link
124     */
125    @Override
126    protected Content getNavLinkPackage() {
127        Content linkContent = getHyperLink(DocPaths.PACKAGE_SUMMARY,
128                contents.packageLabel);
129        Content li = HtmlTree.LI(linkContent);
130        return li;
131    }
132
133    /**
134     * Get the class link.
135     *
136     * @return a content tree for the class link
137     */
138    @Override
139    protected Content getNavLinkClass() {
140        Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, contents.classLabel);
141        return li;
142    }
143
144    /**
145     * Get the class use link.
146     *
147     * @return a content tree for the class use link
148     */
149    @Override
150    protected Content getNavLinkClassUse() {
151        Content linkContent = getHyperLink(DocPaths.CLASS_USE.resolve(filename), contents.useLabel);
152        Content li = HtmlTree.LI(linkContent);
153        return li;
154    }
155
156    /**
157     * Get link to previous class.
158     *
159     * @return a content tree for the previous class link
160     */
161    @Override
162    public Content getNavLinkPrevious() {
163        Content li;
164        if (prev != null) {
165            Content prevLink = getLink(new LinkInfoImpl(configuration,
166                    LinkInfoImpl.Kind.CLASS, prev)
167                    .label(contents.prevClassLabel).strong(true));
168            li = HtmlTree.LI(prevLink);
169        }
170        else
171            li = HtmlTree.LI(contents.prevClassLabel);
172        return li;
173    }
174
175    /**
176     * Get link to next class.
177     *
178     * @return a content tree for the next class link
179     */
180    @Override
181    public Content getNavLinkNext() {
182        Content li;
183        if (next != null) {
184            Content nextLink = getLink(new LinkInfoImpl(configuration,
185                    LinkInfoImpl.Kind.CLASS, next)
186                    .label(contents.nextClassLabel).strong(true));
187            li = HtmlTree.LI(nextLink);
188        }
189        else
190            li = HtmlTree.LI(contents.nextClassLabel);
191        return li;
192    }
193
194    /**
195     * {@inheritDoc}
196     */
197    @Override
198    public Content getHeader(String header) {
199        HtmlTree bodyTree = getBody(true, getWindowTitle(utils.getSimpleName(typeElement)));
200        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
201                ? HtmlTree.HEADER()
202                : bodyTree;
203        addTop(htmlTree);
204        addNavLinks(true, htmlTree);
205        if (configuration.allowTag(HtmlTag.HEADER)) {
206            bodyTree.addContent(htmlTree);
207        }
208        bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA);
209        HtmlTree div = new HtmlTree(HtmlTag.DIV);
210        div.addStyle(HtmlStyle.header);
211        ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(typeElement);
212        if (configuration.showModules) {
213            Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInClass, contents.moduleLabel);
214            Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel);
215            moduleNameDiv.addContent(Contents.SPACE);
216            moduleNameDiv.addContent(getModuleLink(mdle,
217                    new StringContent(mdle.getQualifiedName().toString())));
218            div.addContent(moduleNameDiv);
219        }
220        PackageElement pkg = utils.containingPackage(typeElement);
221        if (!pkg.isUnnamed()) {
222            Content classPackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInClass, contents.packageLabel);
223            Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classPackageLabel);
224            pkgNameDiv.addContent(Contents.SPACE);
225            Content pkgNameContent = getPackageLink(pkg,
226                    new StringContent(utils.getPackageName(pkg)));
227            pkgNameDiv.addContent(pkgNameContent);
228            div.addContent(pkgNameDiv);
229        }
230        LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
231                LinkInfoImpl.Kind.CLASS_HEADER, typeElement);
232        //Let's not link to ourselves in the header.
233        linkInfo.linkToSelf = false;
234        Content headerContent = new StringContent(header);
235        Content heading = HtmlTree.HEADING(HtmlConstants.CLASS_PAGE_HEADING, true,
236                HtmlStyle.title, headerContent);
237        heading.addContent(getTypeParameterLinks(linkInfo));
238        div.addContent(heading);
239        if (configuration.allowTag(HtmlTag.MAIN)) {
240            mainTree.addContent(div);
241        } else {
242            bodyTree.addContent(div);
243        }
244        return bodyTree;
245    }
246
247    /**
248     * {@inheritDoc}
249     */
250    @Override
251    public Content getClassContentHeader() {
252        return getContentHeader();
253    }
254
255    /**
256     * {@inheritDoc}
257     */
258    @Override
259    public void addFooter(Content contentTree) {
260        contentTree.addContent(HtmlConstants.END_OF_CLASS_DATA);
261        Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
262                ? HtmlTree.FOOTER()
263                : contentTree;
264        addNavLinks(false, htmlTree);
265        addBottom(htmlTree);
266        if (configuration.allowTag(HtmlTag.FOOTER)) {
267            contentTree.addContent(htmlTree);
268        }
269    }
270
271    /**
272     * {@inheritDoc}
273     */
274    @Override
275    public void printDocument(Content contentTree) throws IOException {
276        printHtmlDocument(configuration.metakeywords.getMetaKeywords(typeElement),
277                true, contentTree);
278    }
279
280    /**
281     * {@inheritDoc}
282     */
283    @Override
284    public Content getClassInfoTreeHeader() {
285        return getMemberTreeHeader();
286    }
287
288    /**
289     * {@inheritDoc}
290     */
291    @Override
292    public Content getClassInfo(Content classInfoTree) {
293        return getMemberTree(HtmlStyle.description, classInfoTree);
294    }
295
296    /**
297     * {@inheritDoc}
298     */
299    @Override
300    public void addClassSignature(String modifiers, Content classInfoTree) {
301        classInfoTree.addContent(new HtmlTree(HtmlTag.BR));
302        Content pre = new HtmlTree(HtmlTag.PRE);
303        addAnnotationInfo(typeElement, pre);
304        pre.addContent(modifiers);
305        LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
306                LinkInfoImpl.Kind.CLASS_SIGNATURE, typeElement);
307        //Let's not link to ourselves in the signature.
308        linkInfo.linkToSelf = false;
309        Content className = new StringContent(utils.getSimpleName(typeElement));
310        Content parameterLinks = getTypeParameterLinks(linkInfo);
311        if (configuration.linksource) {
312            addSrcLink(typeElement, className, pre);
313            pre.addContent(parameterLinks);
314        } else {
315            Content span = HtmlTree.SPAN(HtmlStyle.typeNameLabel, className);
316            span.addContent(parameterLinks);
317            pre.addContent(span);
318        }
319        if (!utils.isInterface(typeElement)) {
320            TypeMirror superclass = utils.getFirstVisibleSuperClass(typeElement);
321            if (superclass != null) {
322                pre.addContent(DocletConstants.NL);
323                pre.addContent("extends ");
324                Content link = getLink(new LinkInfoImpl(configuration,
325                        LinkInfoImpl.Kind.CLASS_SIGNATURE_PARENT_NAME,
326                        superclass));
327                pre.addContent(link);
328            }
329        }
330        List<? extends TypeMirror> interfaces = typeElement.getInterfaces();
331        if (!interfaces.isEmpty()) {
332            boolean isFirst = true;
333            for (TypeMirror type : interfaces) {
334                TypeElement tDoc = utils.asTypeElement(type);
335                if (!(utils.isPublic(tDoc) || utils.isLinkable(tDoc))) {
336                    continue;
337                }
338                if (isFirst) {
339                    pre.addContent(DocletConstants.NL);
340                    pre.addContent(utils.isInterface(typeElement) ? "extends " : "implements ");
341                    isFirst = false;
342                } else {
343                    pre.addContent(", ");
344                }
345                Content link = getLink(new LinkInfoImpl(configuration,
346                                                        LinkInfoImpl.Kind.CLASS_SIGNATURE_PARENT_NAME,
347                                                        type));
348                pre.addContent(link);
349            }
350        }
351        classInfoTree.addContent(pre);
352    }
353
354    /**
355     * {@inheritDoc}
356     */
357    @Override
358    public void addClassDescription(Content classInfoTree) {
359        if(!configuration.nocomment) {
360            // generate documentation for the class.
361            if (!utils.getBody(typeElement).isEmpty()) {
362                addInlineComment(typeElement, classInfoTree);
363            }
364        }
365    }
366
367    /**
368     * {@inheritDoc}
369     */
370    @Override
371    public void addClassTagInfo(Content classInfoTree) {
372        if(!configuration.nocomment) {
373            // Print Information about all the tags here
374            addTagsInfo(typeElement, classInfoTree);
375        }
376    }
377
378    /**
379     * Get the class hierarchy tree for the given class.
380     *
381     * @param type the class to print the hierarchy for
382     * @return a content tree for class inheritence
383     */
384    private Content getClassInheritenceTree(TypeMirror type) {
385        TypeMirror sup;
386        HtmlTree classTreeUl = new HtmlTree(HtmlTag.UL);
387        classTreeUl.addStyle(HtmlStyle.inheritance);
388        Content liTree = null;
389        do {
390            sup = utils.getFirstVisibleSuperClass(type);
391            if (sup != null) {
392                HtmlTree ul = new HtmlTree(HtmlTag.UL);
393                ul.addStyle(HtmlStyle.inheritance);
394                ul.addContent(getTreeForClassHelper(type));
395                if (liTree != null)
396                    ul.addContent(liTree);
397                Content li = HtmlTree.LI(ul);
398                liTree = li;
399                type = sup;
400            } else
401                classTreeUl.addContent(getTreeForClassHelper(type));
402        } while (sup != null);
403        if (liTree != null)
404            classTreeUl.addContent(liTree);
405        return classTreeUl;
406    }
407
408    /**
409     * Get the class helper tree for the given class.
410     *
411     * @param type the class to print the helper for
412     * @return a content tree for class helper
413     */
414    private Content getTreeForClassHelper(TypeMirror type) {
415        Content li = new HtmlTree(HtmlTag.LI);
416        if (type.equals(typeElement.asType())) {
417            Content typeParameters = getTypeParameterLinks(
418                    new LinkInfoImpl(configuration, LinkInfoImpl.Kind.TREE,
419                    typeElement));
420            if (configuration.shouldExcludeQualifier(utils.containingPackage(typeElement).toString())) {
421                li.addContent(utils.asTypeElement(type).getSimpleName());
422                li.addContent(typeParameters);
423            } else {
424                li.addContent(utils.asTypeElement(type).getQualifiedName());
425                li.addContent(typeParameters);
426            }
427        } else {
428            Content link = getLink(new LinkInfoImpl(configuration,
429                    LinkInfoImpl.Kind.CLASS_TREE_PARENT, type)
430                    .label(configuration.getClassName(utils.asTypeElement(type))));
431            li.addContent(link);
432        }
433        return li;
434    }
435
436    /**
437     * {@inheritDoc}
438     */
439    @Override
440    public void addClassTree(Content classContentTree) {
441        if (!utils.isClass(typeElement)) {
442            return;
443        }
444        classContentTree.addContent(getClassInheritenceTree(typeElement.asType()));
445    }
446
447    /**
448     * {@inheritDoc}
449     */
450    @Override
451    public void addTypeParamInfo(Content classInfoTree) {
452        if (!utils.getTypeParamTrees(typeElement).isEmpty()) {
453            Content typeParam = (new ParamTaglet()).getTagletOutput(typeElement,
454                    getTagletWriterInstance(false));
455            Content dl = HtmlTree.DL(typeParam);
456            classInfoTree.addContent(dl);
457        }
458    }
459
460    /**
461     * {@inheritDoc}
462     */
463    @Override
464    public void addSubClassInfo(Content classInfoTree) {
465        if (utils.isClass(typeElement)) {
466            if (typeElement.getQualifiedName().toString().equals("java.lang.Object") ||
467                    typeElement.getQualifiedName().toString().equals("org.omg.CORBA.Object")) {
468                return;    // Don't generate the list, too huge
469            }
470            Set<TypeElement> subclasses = classtree.directSubClasses(typeElement, false);
471            if (!subclasses.isEmpty()) {
472                Content label = contents.subclassesLabel;
473                Content dt = HtmlTree.DT(label);
474                Content dl = HtmlTree.DL(dt);
475                dl.addContent(getClassLinks(LinkInfoImpl.Kind.SUBCLASSES,
476                        subclasses));
477                classInfoTree.addContent(dl);
478            }
479        }
480    }
481
482    /**
483     * {@inheritDoc}
484     */
485    @Override
486    public void addSubInterfacesInfo(Content classInfoTree) {
487        if (utils.isInterface(typeElement)) {
488            Set<TypeElement> subInterfaces = classtree.allSubClasses(typeElement, false);
489            if (!subInterfaces.isEmpty()) {
490                Content label = contents.subinterfacesLabel;
491                Content dt = HtmlTree.DT(label);
492                Content dl = HtmlTree.DL(dt);
493                dl.addContent(getClassLinks(LinkInfoImpl.Kind.SUBINTERFACES,
494                        subInterfaces));
495                classInfoTree.addContent(dl);
496            }
497        }
498    }
499
500    /**
501     * {@inheritDoc}
502     */
503    @Override
504    public void addInterfaceUsageInfo (Content classInfoTree) {
505        if (!utils.isInterface(typeElement)) {
506            return;
507        }
508        if (typeElement.getQualifiedName().toString().equals("java.lang.Cloneable") ||
509                typeElement.getQualifiedName().toString().equals("java.io.Serializable")) {
510            return;   // Don't generate the list, too big
511        }
512        Set<TypeElement> implcl = classtree.implementingClasses(typeElement);
513        if (!implcl.isEmpty()) {
514            Content label = contents.implementingClassesLabel;
515            Content dt = HtmlTree.DT(label);
516            Content dl = HtmlTree.DL(dt);
517            dl.addContent(getClassLinks(LinkInfoImpl.Kind.IMPLEMENTED_CLASSES,
518                    implcl));
519            classInfoTree.addContent(dl);
520        }
521    }
522
523    /**
524     * {@inheritDoc}
525     */
526    @Override
527    public void addImplementedInterfacesInfo(Content classInfoTree) {
528        SortedSet<TypeMirror> interfaces = new TreeSet<>(utils.makeTypeMirrorClassUseComparator());
529        interfaces.addAll(utils.getAllInterfaces(typeElement));
530        if (utils.isClass(typeElement) && !interfaces.isEmpty()) {
531            Content label = contents.allImplementedInterfacesLabel;
532            Content dt = HtmlTree.DT(label);
533            Content dl = HtmlTree.DL(dt);
534            dl.addContent(getClassLinks(LinkInfoImpl.Kind.IMPLEMENTED_INTERFACES, interfaces));
535            classInfoTree.addContent(dl);
536        }
537    }
538
539    /**
540     * {@inheritDoc}
541     */
542    @Override
543    public void addSuperInterfacesInfo(Content classInfoTree) {
544        SortedSet<TypeMirror> interfaces =
545                new TreeSet<>(utils.makeTypeMirrorIndexUseComparator());
546        interfaces.addAll(utils.getAllInterfaces(typeElement));
547
548        if (utils.isInterface(typeElement) && !interfaces.isEmpty()) {
549            Content label = contents.allSuperinterfacesLabel;
550            Content dt = HtmlTree.DT(label);
551            Content dl = HtmlTree.DL(dt);
552            dl.addContent(getClassLinks(LinkInfoImpl.Kind.SUPER_INTERFACES, interfaces));
553            classInfoTree.addContent(dl);
554        }
555    }
556
557    /**
558     * {@inheritDoc}
559     */
560    @Override
561    public void addNestedClassInfo(final Content classInfoTree) {
562        Element outerClass = typeElement.getEnclosingElement();
563        if (outerClass == null)
564            return;
565        new SimpleElementVisitor8<Void, Void>() {
566            @Override @DefinedBy(Api.LANGUAGE_MODEL)
567            public Void visitType(TypeElement e, Void p) {
568                Content label = utils.isInterface(e)
569                        ? contents.enclosingInterfaceLabel
570                        : contents.enclosingClassLabel;
571                Content dt = HtmlTree.DT(label);
572                Content dl = HtmlTree.DL(dt);
573                Content dd = new HtmlTree(HtmlTag.DD);
574                dd.addContent(getLink(new LinkInfoImpl(configuration,
575                        LinkInfoImpl.Kind.CLASS, e)));
576                dl.addContent(dd);
577                classInfoTree.addContent(dl);
578                return null;
579            }
580        }.visit(outerClass);
581    }
582
583    /**
584     * {@inheritDoc}
585     */
586    @Override
587    public void addFunctionalInterfaceInfo (Content classInfoTree) {
588        if (isFunctionalInterface()) {
589            Content dt = HtmlTree.DT(contents.functionalInterface);
590            Content dl = HtmlTree.DL(dt);
591            Content dd = new HtmlTree(HtmlTag.DD);
592            dd.addContent(contents.functionalInterfaceMessage);
593            dl.addContent(dd);
594            classInfoTree.addContent(dl);
595        }
596    }
597
598    public boolean isFunctionalInterface() {
599        List<? extends AnnotationMirror> annotationMirrors = ((Element) typeElement).getAnnotationMirrors();
600        for (AnnotationMirror anno : annotationMirrors) {
601            if (utils.isFunctionalInterface(anno)) {
602                return true;
603            }
604        }
605        return false;
606    }
607
608
609    /**
610     * {@inheritDoc}
611     */
612    @Override
613    public void addClassDeprecationInfo(Content classInfoTree) {
614        Content hr = new HtmlTree(HtmlTag.HR);
615        classInfoTree.addContent(hr);
616        List<? extends DocTree> deprs = utils.getBlockTags(typeElement, DocTree.Kind.DEPRECATED);
617        if (utils.isDeprecated(typeElement)) {
618            Content deprLabel = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, contents.deprecatedPhrase);
619            Content div = HtmlTree.DIV(HtmlStyle.block, deprLabel);
620            if (!deprs.isEmpty()) {
621                CommentHelper ch = utils.getCommentHelper(typeElement);
622                DocTree dt = deprs.get(0);
623                List<? extends DocTree> commentTags = ch.getBody(configuration, dt);
624                if (!commentTags.isEmpty()) {
625                    div.addContent(Contents.SPACE);
626                    addInlineDeprecatedComment(typeElement, deprs.get(0), div);
627                }
628            }
629            classInfoTree.addContent(div);
630        }
631    }
632
633    /**
634     * Get links to the given classes.
635     *
636     * @param context the id of the context where the link will be printed
637     * @param list the list of classes
638     * @return a content tree for the class list
639     */
640    private Content getClassLinks(LinkInfoImpl.Kind context, Collection<?> list) {
641        Content dd = new HtmlTree(HtmlTag.DD);
642        boolean isFirst = true;
643        for (Object type : list) {
644            if (!isFirst) {
645                Content separator = new StringContent(", ");
646                dd.addContent(separator);
647            } else {
648                isFirst = false;
649            }
650            // TODO: should we simply split this method up to avoid instanceof ?
651            if (type instanceof TypeElement) {
652                Content link = getLink(
653                        new LinkInfoImpl(configuration, context, (TypeElement)(type)));
654                dd.addContent(HtmlTree.CODE(link));
655            } else {
656                Content link = getLink(
657                        new LinkInfoImpl(configuration, context, ((TypeMirror)type)));
658                dd.addContent(HtmlTree.CODE(link));
659            }
660        }
661        return dd;
662    }
663
664    /**
665     * {@inheritDoc}
666     */
667    @Override
668    protected Content getNavLinkTree() {
669        Content treeLinkContent = getHyperLink(DocPaths.PACKAGE_TREE,
670                contents.treeLabel, "", "");
671        Content li = HtmlTree.LI(treeLinkContent);
672        return li;
673    }
674
675    /**
676     * Add summary details to the navigation bar.
677     *
678     * @param subDiv the content tree to which the summary detail links will be added
679     */
680    protected void addSummaryDetailLinks(Content subDiv) {
681        try {
682            Content div = HtmlTree.DIV(getNavSummaryLinks());
683            div.addContent(getNavDetailLinks());
684            subDiv.addContent(div);
685        } catch (Exception e) {
686            throw new DocletAbortException(e);
687        }
688    }
689
690    /**
691     * Get summary links for navigation bar.
692     *
693     * @return the content tree for the navigation summary links
694     */
695    protected Content getNavSummaryLinks() throws Exception {
696        Content li = HtmlTree.LI(contents.summaryLabel);
697        li.addContent(Contents.SPACE);
698        Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li);
699        MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder)
700                configuration.getBuilderFactory().getMemberSummaryBuilder(this);
701        for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.summarySet) {
702            Content liNav = new HtmlTree(HtmlTag.LI);
703            if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !utils.isEnum(typeElement)) {
704                continue;
705            }
706            if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && utils.isEnum(typeElement)) {
707                continue;
708            }
709            AbstractMemberWriter writer =
710                ((AbstractMemberWriter) memberSummaryBuilder.getMemberSummaryWriter(kind));
711            if (writer == null) {
712                liNav.addContent(contents.getContent(VisibleMemberMap.Kind.getNavLinkLabels(kind)));
713            } else {
714                writer.addNavSummaryLink(
715                        memberSummaryBuilder.members(kind),
716                        memberSummaryBuilder.getVisibleMemberMap(kind), liNav);
717            }
718            if (kind != Kind.METHODS) {
719                addNavGap(liNav);
720            }
721            ulNav.addContent(liNav);
722        }
723        return ulNav;
724    }
725
726    /**
727     * Get detail links for the navigation bar.
728     *
729     * @return the content tree for the detail links
730     * @throws java.lang.Exception
731     */
732    protected Content getNavDetailLinks() throws Exception {
733        Content li = HtmlTree.LI(contents.detailLabel);
734        li.addContent(Contents.SPACE);
735        Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li);
736        MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder)
737                configuration.getBuilderFactory().getMemberSummaryBuilder(this);
738        for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.detailSet) {
739            Content liNav = new HtmlTree(HtmlTag.LI);
740            AbstractMemberWriter writer =
741                    ((AbstractMemberWriter) memberSummaryBuilder.
742                    getMemberSummaryWriter(kind));
743            if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !utils.isEnum(typeElement)) {
744                continue;
745            }
746            if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && utils.isEnum(typeElement)) {
747                continue;
748            }
749            if (writer == null) {
750                liNav.addContent(contents.getContent(VisibleMemberMap.Kind.getNavLinkLabels(kind)));
751            } else {
752                writer.addNavDetailLink(memberSummaryBuilder.members(kind), liNav);
753            }
754            if (kind != Kind.METHODS) {
755                addNavGap(liNav);
756            }
757            ulNav.addContent(liNav);
758        }
759        return ulNav;
760    }
761
762    /**
763     * Return the TypeElement being documented.
764     *
765     * @return the TypeElement being documented.
766     */
767    @Override
768    public TypeElement getTypeElement() {
769        return typeElement;
770    }
771}
772