ClassWriterImpl.java revision 3824:376ee1fd40c3
1107120Sjulian/*
2107120Sjulian * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
3107120Sjulian * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4107120Sjulian *
5107120Sjulian * This code is free software; you can redistribute it and/or modify it
6107120Sjulian * under the terms of the GNU General Public License version 2 only, as
7107120Sjulian * published by the Free Software Foundation.  Oracle designates this
8107120Sjulian * particular file as subject to the "Classpath" exception as provided
9107120Sjulian * by Oracle in the LICENSE file that accompanied this code.
10107120Sjulian *
11107120Sjulian * This code is distributed in the hope that it will be useful, but WITHOUT
12107120Sjulian * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13107120Sjulian * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14107120Sjulian * version 2 for more details (a copy is included in the LICENSE file that
15107120Sjulian * accompanied this code).
16107120Sjulian *
17107120Sjulian * You should have received a copy of the GNU General Public License version
18107120Sjulian * 2 along with this work; if not, write to the Free Software Foundation,
19107120Sjulian * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20107120Sjulian *
21107120Sjulian * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22107120Sjulian * or visit www.oracle.com if you need additional information or have any
23107120Sjulian * questions.
24107120Sjulian */
25107120Sjulian
26107120Sjulianpackage jdk.javadoc.internal.doclets.formats.html;
27107120Sjulian
28121054Semaximport java.util.*;
29107120Sjulian
30107120Sjulianimport javax.lang.model.element.AnnotationMirror;
31107120Sjulianimport javax.lang.model.element.Element;
32107120Sjulianimport javax.lang.model.element.ModuleElement;
33107120Sjulianimport javax.lang.model.element.PackageElement;
34107120Sjulianimport javax.lang.model.element.TypeElement;
35107120Sjulianimport javax.lang.model.type.TypeMirror;
36107120Sjulianimport javax.lang.model.util.SimpleElementVisitor8;
37121054Semax
38107120Sjulianimport com.sun.source.doctree.DocTree;
39107120Sjulianimport jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
40107120Sjulianimport jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
41107120Sjulianimport jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
42107120Sjulianimport jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
43107120Sjulianimport jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
44107120Sjulianimport jdk.javadoc.internal.doclets.toolkit.ClassWriter;
45107120Sjulianimport jdk.javadoc.internal.doclets.toolkit.Content;
46107120Sjulianimport jdk.javadoc.internal.doclets.toolkit.builders.MemberSummaryBuilder;
47107120Sjulianimport jdk.javadoc.internal.doclets.toolkit.taglets.ParamTaglet;
48107120Sjulianimport jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
49107120Sjulianimport jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
50107120Sjulianimport jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
51107120Sjulianimport jdk.javadoc.internal.doclets.toolkit.util.DocPath;
52107120Sjulianimport jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
53107120Sjulianimport jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
54107120Sjulianimport jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
55107120Sjulianimport jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind;
56107120Sjulian
57107120Sjulian/**
58107120Sjulian * Generate the Class Information Page.
59107120Sjulian *
60107120Sjulian *  <p><b>This is NOT part of any supported API.
61107120Sjulian *  If you write code that depends on this, you do so at your own risk.
62107120Sjulian *  This code and its internal interfaces are subject to change or
63107120Sjulian *  deletion without notice.</b>
64107120Sjulian *
65107120Sjulian * @see javax.lang.model.element.TypeElement
66107120Sjulian * @see java.util.Collections
67107120Sjulian * @see java.util.List
68107120Sjulian * @see java.util.ArrayList
69114879Sjulian * @see java.util.HashMap
70107120Sjulian *
71107120Sjulian * @author Atul M Dambalkar
72107120Sjulian * @author Robert Field
73107120Sjulian * @author Bhavesh Patel (Modified)
74107120Sjulian */
75107120Sjulianpublic class ClassWriterImpl extends SubWriterHolderWriter implements ClassWriter {
76107120Sjulian
77107120Sjulian    protected final TypeElement typeElement;
78107120Sjulian
79107120Sjulian    protected final ClassTree classtree;
80107120Sjulian
81107120Sjulian    protected final TypeElement prev;
82107120Sjulian
83107120Sjulian    protected final TypeElement next;
84107120Sjulian
85107120Sjulian    /**
86107120Sjulian     * @param configuration the configuration data for the doclet
87107120Sjulian     * @param typeElement the class being documented.
88107120Sjulian     * @param prevClass the previous class that was documented.
89114879Sjulian     * @param nextClass the next class being documented.
90107120Sjulian     * @param classTree the class tree for the given class.
91107120Sjulian     */
92107120Sjulian    public ClassWriterImpl(ConfigurationImpl configuration, TypeElement typeElement,
93107120Sjulian            TypeElement prevClass, TypeElement nextClass, ClassTree classTree) {
94107120Sjulian        super(configuration, DocPath.forClass(configuration.utils, typeElement));
95107120Sjulian        this.typeElement = typeElement;
96107120Sjulian        configuration.currentTypeElement = typeElement;
97107120Sjulian        this.classtree = classTree;
98107120Sjulian        this.prev = prevClass;
99107120Sjulian        this.next = nextClass;
100107120Sjulian    }
101107120Sjulian
102107120Sjulian    /**
103107120Sjulian     * Get the module link.
104188130Semax     *
105188130Semax     * @return a content tree for the module link
106188130Semax     */
107188130Semax    @Override
108107120Sjulian    protected Content getNavLinkModule() {
109107120Sjulian        Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(typeElement),
110107120Sjulian                contents.moduleLabel);
111107120Sjulian        Content li = HtmlTree.LI(linkContent);
112107120Sjulian        return li;
113107120Sjulian    }
114107120Sjulian
115107120Sjulian    /**
116107120Sjulian     * Get this package link.
117107120Sjulian     *
118107120Sjulian     * @return a content tree for the package link
119107120Sjulian     */
120107120Sjulian    @Override
121107120Sjulian    protected Content getNavLinkPackage() {
122107120Sjulian        Content linkContent = getHyperLink(DocPaths.PACKAGE_SUMMARY,
123107120Sjulian                contents.packageLabel);
124107120Sjulian        Content li = HtmlTree.LI(linkContent);
125107120Sjulian        return li;
126107120Sjulian    }
127107120Sjulian
128107120Sjulian    /**
129107120Sjulian     * Get the class link.
130107120Sjulian     *
131107120Sjulian     * @return a content tree for the class link
132107120Sjulian     */
133107120Sjulian    @Override
134107120Sjulian    protected Content getNavLinkClass() {
135107120Sjulian        Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, contents.classLabel);
136107120Sjulian        return li;
137107120Sjulian    }
138107120Sjulian
139107120Sjulian    /**
140107120Sjulian     * Get the class use link.
141107120Sjulian     *
142107120Sjulian     * @return a content tree for the class use link
143107120Sjulian     */
144107120Sjulian    @Override
145107120Sjulian    protected Content getNavLinkClassUse() {
146107120Sjulian        Content linkContent = getHyperLink(DocPaths.CLASS_USE.resolve(filename), contents.useLabel);
147107120Sjulian        Content li = HtmlTree.LI(linkContent);
148107120Sjulian        return li;
149107120Sjulian    }
150107120Sjulian
151107120Sjulian    /**
152107120Sjulian     * Get link to previous class.
153107120Sjulian     *
154107120Sjulian     * @return a content tree for the previous class link
155107120Sjulian     */
156107120Sjulian    @Override
157107120Sjulian    public Content getNavLinkPrevious() {
158107120Sjulian        Content li;
159107120Sjulian        if (prev != null) {
160107120Sjulian            Content prevLink = getLink(new LinkInfoImpl(configuration,
161107120Sjulian                    LinkInfoImpl.Kind.CLASS, prev)
162107120Sjulian                    .label(contents.prevClassLabel).strong(true));
163122758Sharti            li = HtmlTree.LI(prevLink);
164107120Sjulian        }
165107120Sjulian        else
166107120Sjulian            li = HtmlTree.LI(contents.prevClassLabel);
167107120Sjulian        return li;
168107120Sjulian    }
169107120Sjulian
170107120Sjulian    /**
171107120Sjulian     * Get link to next class.
172107120Sjulian     *
173107120Sjulian     * @return a content tree for the next class link
174107120Sjulian     */
175107120Sjulian    @Override
176107120Sjulian    public Content getNavLinkNext() {
177107120Sjulian        Content li;
178107120Sjulian        if (next != null) {
179107120Sjulian            Content nextLink = getLink(new LinkInfoImpl(configuration,
180107120Sjulian                    LinkInfoImpl.Kind.CLASS, next)
181107120Sjulian                    .label(contents.nextClassLabel).strong(true));
182107120Sjulian            li = HtmlTree.LI(nextLink);
183107120Sjulian        }
184107120Sjulian        else
185107120Sjulian            li = HtmlTree.LI(contents.nextClassLabel);
186107120Sjulian        return li;
187107120Sjulian    }
188107120Sjulian
189107120Sjulian    /**
190107120Sjulian     * {@inheritDoc}
191107120Sjulian     */
192107120Sjulian    @Override
193107120Sjulian    public Content getHeader(String header) {
194107120Sjulian        HtmlTree bodyTree = getBody(true, getWindowTitle(utils.getSimpleName(typeElement)));
195107120Sjulian        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
196107120Sjulian                ? HtmlTree.HEADER()
197107120Sjulian                : bodyTree;
198107120Sjulian        addTop(htmlTree);
199107120Sjulian        addNavLinks(true, htmlTree);
200107120Sjulian        if (configuration.allowTag(HtmlTag.HEADER)) {
201107120Sjulian            bodyTree.addContent(htmlTree);
202107120Sjulian        }
203107120Sjulian        bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA);
204107120Sjulian        HtmlTree div = new HtmlTree(HtmlTag.DIV);
205107120Sjulian        div.addStyle(HtmlStyle.header);
206107120Sjulian        if (configuration.showModules) {
207107120Sjulian            ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(typeElement);
208107120Sjulian            Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInClass, contents.moduleLabel);
209107120Sjulian            Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel);
210107120Sjulian            moduleNameDiv.addContent(Contents.SPACE);
211107120Sjulian            moduleNameDiv.addContent(getModuleLink(mdle,
212107120Sjulian                    new StringContent(mdle.getQualifiedName().toString())));
213107120Sjulian            div.addContent(moduleNameDiv);
214107120Sjulian        }
215107120Sjulian        PackageElement pkg = utils.containingPackage(typeElement);
216107120Sjulian        if (!pkg.isUnnamed()) {
217107120Sjulian            Content classPackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInClass, contents.packageLabel);
218107120Sjulian            Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classPackageLabel);
219107120Sjulian            pkgNameDiv.addContent(Contents.SPACE);
220107120Sjulian            Content pkgNameContent = getPackageLink(pkg,
221107120Sjulian                    new StringContent(utils.getPackageName(pkg)));
222107120Sjulian            pkgNameDiv.addContent(pkgNameContent);
223107120Sjulian            div.addContent(pkgNameDiv);
224107120Sjulian        }
225107120Sjulian        LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
226107120Sjulian                LinkInfoImpl.Kind.CLASS_HEADER, typeElement);
227107120Sjulian        //Let's not link to ourselves in the header.
228107120Sjulian        linkInfo.linkToSelf = false;
229107120Sjulian        Content headerContent = new StringContent(header);
230107120Sjulian        Content heading = HtmlTree.HEADING(HtmlConstants.CLASS_PAGE_HEADING, true,
231107120Sjulian                HtmlStyle.title, headerContent);
232107120Sjulian        heading.addContent(getTypeParameterLinks(linkInfo));
233107120Sjulian        div.addContent(heading);
234107120Sjulian        if (configuration.allowTag(HtmlTag.MAIN)) {
235107120Sjulian            mainTree.addContent(div);
236107120Sjulian        } else {
237107120Sjulian            bodyTree.addContent(div);
238107120Sjulian        }
239107120Sjulian        return bodyTree;
240107120Sjulian    }
241107120Sjulian
242107120Sjulian    /**
243107120Sjulian     * {@inheritDoc}
244107120Sjulian     */
245107120Sjulian    @Override
246107120Sjulian    public Content getClassContentHeader() {
247107120Sjulian        return getContentHeader();
248107120Sjulian    }
249107120Sjulian
250107120Sjulian    /**
251107120Sjulian     * {@inheritDoc}
252107120Sjulian     */
253107120Sjulian    @Override
254107120Sjulian    public void addFooter(Content contentTree) {
255107120Sjulian        contentTree.addContent(HtmlConstants.END_OF_CLASS_DATA);
256107120Sjulian        Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
257107120Sjulian                ? HtmlTree.FOOTER()
258114879Sjulian                : contentTree;
259107120Sjulian        addNavLinks(false, htmlTree);
260244040Seadler        addBottom(htmlTree);
261107120Sjulian        if (configuration.allowTag(HtmlTag.FOOTER)) {
262107120Sjulian            contentTree.addContent(htmlTree);
263114879Sjulian        }
264114879Sjulian    }
265107120Sjulian
266107120Sjulian    /**
267107120Sjulian     * {@inheritDoc}
268107120Sjulian     */
269    @Override
270    public void printDocument(Content contentTree) throws DocFileIOException {
271        printHtmlDocument(configuration.metakeywords.getMetaKeywords(typeElement),
272                true, contentTree);
273    }
274
275    /**
276     * {@inheritDoc}
277     */
278    @Override
279    public Content getClassInfoTreeHeader() {
280        return getMemberTreeHeader();
281    }
282
283    /**
284     * {@inheritDoc}
285     */
286    @Override
287    public Content getClassInfo(Content classInfoTree) {
288        return getMemberTree(HtmlStyle.description, classInfoTree);
289    }
290
291    /**
292     * {@inheritDoc}
293     */
294    @Override
295    public void addClassSignature(String modifiers, Content classInfoTree) {
296        classInfoTree.addContent(new HtmlTree(HtmlTag.BR));
297        Content pre = new HtmlTree(HtmlTag.PRE);
298        addAnnotationInfo(typeElement, pre);
299        pre.addContent(modifiers);
300        LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
301                LinkInfoImpl.Kind.CLASS_SIGNATURE, typeElement);
302        //Let's not link to ourselves in the signature.
303        linkInfo.linkToSelf = false;
304        Content className = new StringContent(utils.getSimpleName(typeElement));
305        Content parameterLinks = getTypeParameterLinks(linkInfo);
306        if (configuration.linksource) {
307            addSrcLink(typeElement, className, pre);
308            pre.addContent(parameterLinks);
309        } else {
310            Content span = HtmlTree.SPAN(HtmlStyle.typeNameLabel, className);
311            span.addContent(parameterLinks);
312            pre.addContent(span);
313        }
314        if (!utils.isInterface(typeElement)) {
315            TypeMirror superclass = utils.getFirstVisibleSuperClass(typeElement);
316            if (superclass != null) {
317                pre.addContent(DocletConstants.NL);
318                pre.addContent("extends ");
319                Content link = getLink(new LinkInfoImpl(configuration,
320                        LinkInfoImpl.Kind.CLASS_SIGNATURE_PARENT_NAME,
321                        superclass));
322                pre.addContent(link);
323            }
324        }
325        List<? extends TypeMirror> interfaces = typeElement.getInterfaces();
326        if (!interfaces.isEmpty()) {
327            boolean isFirst = true;
328            for (TypeMirror type : interfaces) {
329                TypeElement tDoc = utils.asTypeElement(type);
330                if (!(utils.isPublic(tDoc) || utils.isLinkable(tDoc))) {
331                    continue;
332                }
333                if (isFirst) {
334                    pre.addContent(DocletConstants.NL);
335                    pre.addContent(utils.isInterface(typeElement) ? "extends " : "implements ");
336                    isFirst = false;
337                } else {
338                    pre.addContent(", ");
339                }
340                Content link = getLink(new LinkInfoImpl(configuration,
341                                                        LinkInfoImpl.Kind.CLASS_SIGNATURE_PARENT_NAME,
342                                                        type));
343                pre.addContent(link);
344            }
345        }
346        classInfoTree.addContent(pre);
347    }
348
349    /**
350     * {@inheritDoc}
351     */
352    @Override
353    public void addClassDescription(Content classInfoTree) {
354        if(!configuration.nocomment) {
355            // generate documentation for the class.
356            if (!utils.getFullBody(typeElement).isEmpty()) {
357                addInlineComment(typeElement, classInfoTree);
358            }
359        }
360    }
361
362    /**
363     * {@inheritDoc}
364     */
365    @Override
366    public void addClassTagInfo(Content classInfoTree) {
367        if(!configuration.nocomment) {
368            // Print Information about all the tags here
369            addTagsInfo(typeElement, classInfoTree);
370        }
371    }
372
373    /**
374     * Get the class hierarchy tree for the given class.
375     *
376     * @param type the class to print the hierarchy for
377     * @return a content tree for class inheritence
378     */
379    private Content getClassInheritenceTree(TypeMirror type) {
380        TypeMirror sup;
381        HtmlTree classTreeUl = new HtmlTree(HtmlTag.UL);
382        classTreeUl.addStyle(HtmlStyle.inheritance);
383        Content liTree = null;
384        do {
385            sup = utils.getFirstVisibleSuperClass(type);
386            if (sup != null) {
387                HtmlTree ul = new HtmlTree(HtmlTag.UL);
388                ul.addStyle(HtmlStyle.inheritance);
389                ul.addContent(getTreeForClassHelper(type));
390                if (liTree != null)
391                    ul.addContent(liTree);
392                Content li = HtmlTree.LI(ul);
393                liTree = li;
394                type = sup;
395            } else
396                classTreeUl.addContent(getTreeForClassHelper(type));
397        } while (sup != null);
398        if (liTree != null)
399            classTreeUl.addContent(liTree);
400        return classTreeUl;
401    }
402
403    /**
404     * Get the class helper tree for the given class.
405     *
406     * @param type the class to print the helper for
407     * @return a content tree for class helper
408     */
409    private Content getTreeForClassHelper(TypeMirror type) {
410        Content li = new HtmlTree(HtmlTag.LI);
411        if (type.equals(typeElement.asType())) {
412            Content typeParameters = getTypeParameterLinks(
413                    new LinkInfoImpl(configuration, LinkInfoImpl.Kind.TREE,
414                    typeElement));
415            if (configuration.shouldExcludeQualifier(utils.containingPackage(typeElement).toString())) {
416                li.addContent(utils.asTypeElement(type).getSimpleName());
417                li.addContent(typeParameters);
418            } else {
419                li.addContent(utils.asTypeElement(type).getQualifiedName());
420                li.addContent(typeParameters);
421            }
422        } else {
423            Content link = getLink(new LinkInfoImpl(configuration,
424                    LinkInfoImpl.Kind.CLASS_TREE_PARENT, type)
425                    .label(configuration.getClassName(utils.asTypeElement(type))));
426            li.addContent(link);
427        }
428        return li;
429    }
430
431    /**
432     * {@inheritDoc}
433     */
434    @Override
435    public void addClassTree(Content classContentTree) {
436        if (!utils.isClass(typeElement)) {
437            return;
438        }
439        classContentTree.addContent(getClassInheritenceTree(typeElement.asType()));
440    }
441
442    /**
443     * {@inheritDoc}
444     */
445    @Override
446    public void addTypeParamInfo(Content classInfoTree) {
447        if (!utils.getTypeParamTrees(typeElement).isEmpty()) {
448            Content typeParam = (new ParamTaglet()).getTagletOutput(typeElement,
449                    getTagletWriterInstance(false));
450            Content dl = HtmlTree.DL(typeParam);
451            classInfoTree.addContent(dl);
452        }
453    }
454
455    /**
456     * {@inheritDoc}
457     */
458    @Override
459    public void addSubClassInfo(Content classInfoTree) {
460        if (utils.isClass(typeElement)) {
461            if (typeElement.getQualifiedName().toString().equals("java.lang.Object") ||
462                    typeElement.getQualifiedName().toString().equals("org.omg.CORBA.Object")) {
463                return;    // Don't generate the list, too huge
464            }
465            Set<TypeElement> subclasses = classtree.directSubClasses(typeElement, false);
466            if (!subclasses.isEmpty()) {
467                Content label = contents.subclassesLabel;
468                Content dt = HtmlTree.DT(label);
469                Content dl = HtmlTree.DL(dt);
470                dl.addContent(getClassLinks(LinkInfoImpl.Kind.SUBCLASSES,
471                        subclasses));
472                classInfoTree.addContent(dl);
473            }
474        }
475    }
476
477    /**
478     * {@inheritDoc}
479     */
480    @Override
481    public void addSubInterfacesInfo(Content classInfoTree) {
482        if (utils.isInterface(typeElement)) {
483            Set<TypeElement> subInterfaces = classtree.allSubClasses(typeElement, false);
484            if (!subInterfaces.isEmpty()) {
485                Content label = contents.subinterfacesLabel;
486                Content dt = HtmlTree.DT(label);
487                Content dl = HtmlTree.DL(dt);
488                dl.addContent(getClassLinks(LinkInfoImpl.Kind.SUBINTERFACES,
489                        subInterfaces));
490                classInfoTree.addContent(dl);
491            }
492        }
493    }
494
495    /**
496     * {@inheritDoc}
497     */
498    @Override
499    public void addInterfaceUsageInfo (Content classInfoTree) {
500        if (!utils.isInterface(typeElement)) {
501            return;
502        }
503        if (typeElement.getQualifiedName().toString().equals("java.lang.Cloneable") ||
504                typeElement.getQualifiedName().toString().equals("java.io.Serializable")) {
505            return;   // Don't generate the list, too big
506        }
507        Set<TypeElement> implcl = classtree.implementingClasses(typeElement);
508        if (!implcl.isEmpty()) {
509            Content label = contents.implementingClassesLabel;
510            Content dt = HtmlTree.DT(label);
511            Content dl = HtmlTree.DL(dt);
512            dl.addContent(getClassLinks(LinkInfoImpl.Kind.IMPLEMENTED_CLASSES,
513                    implcl));
514            classInfoTree.addContent(dl);
515        }
516    }
517
518    /**
519     * {@inheritDoc}
520     */
521    @Override
522    public void addImplementedInterfacesInfo(Content classInfoTree) {
523        SortedSet<TypeMirror> interfaces = new TreeSet<>(utils.makeTypeMirrorClassUseComparator());
524        interfaces.addAll(utils.getAllInterfaces(typeElement));
525        if (utils.isClass(typeElement) && !interfaces.isEmpty()) {
526            Content label = contents.allImplementedInterfacesLabel;
527            Content dt = HtmlTree.DT(label);
528            Content dl = HtmlTree.DL(dt);
529            dl.addContent(getClassLinks(LinkInfoImpl.Kind.IMPLEMENTED_INTERFACES, interfaces));
530            classInfoTree.addContent(dl);
531        }
532    }
533
534    /**
535     * {@inheritDoc}
536     */
537    @Override
538    public void addSuperInterfacesInfo(Content classInfoTree) {
539        SortedSet<TypeMirror> interfaces =
540                new TreeSet<>(utils.makeTypeMirrorIndexUseComparator());
541        interfaces.addAll(utils.getAllInterfaces(typeElement));
542
543        if (utils.isInterface(typeElement) && !interfaces.isEmpty()) {
544            Content label = contents.allSuperinterfacesLabel;
545            Content dt = HtmlTree.DT(label);
546            Content dl = HtmlTree.DL(dt);
547            dl.addContent(getClassLinks(LinkInfoImpl.Kind.SUPER_INTERFACES, interfaces));
548            classInfoTree.addContent(dl);
549        }
550    }
551
552    /**
553     * {@inheritDoc}
554     */
555    @Override
556    public void addNestedClassInfo(final Content classInfoTree) {
557        Element outerClass = typeElement.getEnclosingElement();
558        if (outerClass == null)
559            return;
560        new SimpleElementVisitor8<Void, Void>() {
561            @Override
562            public Void visitType(TypeElement e, Void p) {
563                Content label = utils.isInterface(e)
564                        ? contents.enclosingInterfaceLabel
565                        : contents.enclosingClassLabel;
566                Content dt = HtmlTree.DT(label);
567                Content dl = HtmlTree.DL(dt);
568                Content dd = new HtmlTree(HtmlTag.DD);
569                dd.addContent(getLink(new LinkInfoImpl(configuration,
570                        LinkInfoImpl.Kind.CLASS, e)));
571                dl.addContent(dd);
572                classInfoTree.addContent(dl);
573                return null;
574            }
575        }.visit(outerClass);
576    }
577
578    /**
579     * {@inheritDoc}
580     */
581    @Override
582    public void addFunctionalInterfaceInfo (Content classInfoTree) {
583        if (isFunctionalInterface()) {
584            Content dt = HtmlTree.DT(contents.functionalInterface);
585            Content dl = HtmlTree.DL(dt);
586            Content dd = new HtmlTree(HtmlTag.DD);
587            dd.addContent(contents.functionalInterfaceMessage);
588            dl.addContent(dd);
589            classInfoTree.addContent(dl);
590        }
591    }
592
593    public boolean isFunctionalInterface() {
594        List<? extends AnnotationMirror> annotationMirrors = ((Element) typeElement).getAnnotationMirrors();
595        for (AnnotationMirror anno : annotationMirrors) {
596            if (utils.isFunctionalInterface(anno)) {
597                return true;
598            }
599        }
600        return false;
601    }
602
603
604    /**
605     * {@inheritDoc}
606     */
607    @Override
608    public void addClassDeprecationInfo(Content classInfoTree) {
609        Content hr = new HtmlTree(HtmlTag.HR);
610        classInfoTree.addContent(hr);
611        List<? extends DocTree> deprs = utils.getBlockTags(typeElement, DocTree.Kind.DEPRECATED);
612        if (utils.isDeprecated(typeElement)) {
613            Content deprLabel = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(typeElement));
614            Content div = HtmlTree.DIV(HtmlStyle.block, deprLabel);
615            if (!deprs.isEmpty()) {
616                CommentHelper ch = utils.getCommentHelper(typeElement);
617                DocTree dt = deprs.get(0);
618                List<? extends DocTree> commentTags = ch.getBody(configuration, dt);
619                if (!commentTags.isEmpty()) {
620                    div.addContent(Contents.SPACE);
621                    addInlineDeprecatedComment(typeElement, deprs.get(0), div);
622                }
623            }
624            classInfoTree.addContent(div);
625        }
626    }
627
628    /**
629     * Get links to the given classes.
630     *
631     * @param context the id of the context where the link will be printed
632     * @param list the list of classes
633     * @return a content tree for the class list
634     */
635    private Content getClassLinks(LinkInfoImpl.Kind context, Collection<?> list) {
636        Content dd = new HtmlTree(HtmlTag.DD);
637        boolean isFirst = true;
638        for (Object type : list) {
639            if (!isFirst) {
640                Content separator = new StringContent(", ");
641                dd.addContent(separator);
642            } else {
643                isFirst = false;
644            }
645            // TODO: should we simply split this method up to avoid instanceof ?
646            if (type instanceof TypeElement) {
647                Content link = getLink(
648                        new LinkInfoImpl(configuration, context, (TypeElement)(type)));
649                dd.addContent(HtmlTree.CODE(link));
650            } else {
651                Content link = getLink(
652                        new LinkInfoImpl(configuration, context, ((TypeMirror)type)));
653                dd.addContent(HtmlTree.CODE(link));
654            }
655        }
656        return dd;
657    }
658
659    /**
660     * {@inheritDoc}
661     */
662    @Override
663    protected Content getNavLinkTree() {
664        Content treeLinkContent = getHyperLink(DocPaths.PACKAGE_TREE,
665                contents.treeLabel, "", "");
666        Content li = HtmlTree.LI(treeLinkContent);
667        return li;
668    }
669
670    /**
671     * Add summary details to the navigation bar.
672     *
673     * @param subDiv the content tree to which the summary detail links will be added
674     */
675    @Override
676    protected void addSummaryDetailLinks(Content subDiv) {
677        Content div = HtmlTree.DIV(getNavSummaryLinks());
678        div.addContent(getNavDetailLinks());
679        subDiv.addContent(div);
680    }
681
682    /**
683     * Get summary links for navigation bar.
684     *
685     * @return the content tree for the navigation summary links
686     */
687    protected Content getNavSummaryLinks() {
688        Content li = HtmlTree.LI(contents.summaryLabel);
689        li.addContent(Contents.SPACE);
690        Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li);
691        MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder)
692                configuration.getBuilderFactory().getMemberSummaryBuilder(this);
693        for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.summarySet) {
694            Content liNav = new HtmlTree(HtmlTag.LI);
695            if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !utils.isEnum(typeElement)) {
696                continue;
697            }
698            if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && utils.isEnum(typeElement)) {
699                continue;
700            }
701            AbstractMemberWriter writer =
702                ((AbstractMemberWriter) memberSummaryBuilder.getMemberSummaryWriter(kind));
703            if (writer == null) {
704                liNav.addContent(contents.getContent(VisibleMemberMap.Kind.getNavLinkLabels(kind)));
705            } else {
706                writer.addNavSummaryLink(
707                        memberSummaryBuilder.members(kind),
708                        memberSummaryBuilder.getVisibleMemberMap(kind), liNav);
709            }
710            if (kind != Kind.METHODS) {
711                addNavGap(liNav);
712            }
713            ulNav.addContent(liNav);
714        }
715        return ulNav;
716    }
717
718    /**
719     * Get detail links for the navigation bar.
720     *
721     * @return the content tree for the detail links
722     */
723    protected Content getNavDetailLinks() {
724        Content li = HtmlTree.LI(contents.detailLabel);
725        li.addContent(Contents.SPACE);
726        Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li);
727        MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder)
728                configuration.getBuilderFactory().getMemberSummaryBuilder(this);
729        for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.detailSet) {
730            Content liNav = new HtmlTree(HtmlTag.LI);
731            AbstractMemberWriter writer =
732                    ((AbstractMemberWriter) memberSummaryBuilder.
733                    getMemberSummaryWriter(kind));
734            if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !utils.isEnum(typeElement)) {
735                continue;
736            }
737            if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && utils.isEnum(typeElement)) {
738                continue;
739            }
740            if (writer == null) {
741                liNav.addContent(contents.getContent(VisibleMemberMap.Kind.getNavLinkLabels(kind)));
742            } else {
743                writer.addNavDetailLink(memberSummaryBuilder.members(kind), liNav);
744            }
745            if (kind != Kind.METHODS) {
746                addNavGap(liNav);
747            }
748            ulNav.addContent(liNav);
749        }
750        return ulNav;
751    }
752
753    /**
754     * Return the TypeElement being documented.
755     *
756     * @return the TypeElement being documented.
757     */
758    @Override
759    public TypeElement getTypeElement() {
760        return typeElement;
761    }
762}
763