ModuleWriterImpl.java revision 3792:d516975e8110
1/*
2 * Copyright (c) 2013, 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.util.ArrayList;
29import java.util.EnumMap;
30import java.util.List;
31import java.util.Map;
32
33import javax.lang.model.element.ModuleElement;
34import javax.lang.model.element.ModuleElement.DirectiveKind;
35import javax.lang.model.element.PackageElement;
36import javax.lang.model.element.TypeElement;
37
38import com.sun.source.doctree.DocTree;
39import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
40import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
41import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
42import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
43import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
44import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
45import jdk.javadoc.internal.doclets.toolkit.Content;
46import jdk.javadoc.internal.doclets.toolkit.ModuleSummaryWriter;
47import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
48import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
49import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
50
51/**
52 * Class to generate file for each module contents in the right-hand
53 * frame. This will list all the packages and Class Kinds in the module. A click on any
54 * class-kind will update the frame with the clicked class-kind page. A click on any
55 * package will update the frame with the clicked module package page.
56 *
57 *  <p><b>This is NOT part of any supported API.
58 *  If you write code that depends on this, you do so at your own risk.
59 *  This code and its internal interfaces are subject to change or
60 *  deletion without notice.</b>
61 *
62 * @author Bhavesh Patel
63 */
64public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryWriter {
65
66    /**
67     * The prev module name in the alpha-order list.
68     */
69    protected ModuleElement prevModule;
70
71    /**
72     * The next module name in the alpha-order list.
73     */
74    protected ModuleElement nextModule;
75
76    /**
77     * The module being documented.
78     */
79    protected ModuleElement mdle;
80
81    private final Map<ModuleElement.DirectiveKind, List<ModuleElement.Directive>> directiveMap
82            = new EnumMap<>(ModuleElement.DirectiveKind.class);
83
84    /**
85     * The HTML tree for main tag.
86     */
87    protected HtmlTree mainTree = HtmlTree.MAIN();
88
89    /**
90     * The HTML tree for section tag.
91     */
92    protected HtmlTree sectionTree = HtmlTree.SECTION();
93
94    /**
95     * Constructor to construct ModuleWriter object and to generate
96     * "moduleName-summary.html" file.
97     *
98     * @param configuration the configuration of the doclet.
99     * @param mdle        Module under consideration.
100     * @param prevModule   Previous module in the sorted array.
101     * @param nextModule   Next module in the sorted array.
102     */
103    public ModuleWriterImpl(ConfigurationImpl configuration,
104            ModuleElement mdle, ModuleElement prevModule, ModuleElement nextModule) {
105        super(configuration, DocPaths.moduleSummary(mdle));
106        this.prevModule = prevModule;
107        this.nextModule = nextModule;
108        this.mdle = mdle;
109        generateDirectiveMap();
110    }
111
112    /**
113     * Get the module header.
114     *
115     * @param heading the heading for the section
116     */
117    @Override
118    public Content getModuleHeader(String heading) {
119        HtmlTree bodyTree = getBody(true, getWindowTitle(mdle.getQualifiedName().toString()));
120        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
121                ? HtmlTree.HEADER()
122                : bodyTree;
123        addTop(htmlTree);
124        addNavLinks(true, htmlTree);
125        if (configuration.allowTag(HtmlTag.HEADER)) {
126            bodyTree.addContent(htmlTree);
127        }
128        HtmlTree div = new HtmlTree(HtmlTag.DIV);
129        div.addStyle(HtmlStyle.header);
130        Content annotationContent = new HtmlTree(HtmlTag.P);
131        addAnnotationInfo(mdle, annotationContent);
132        div.addContent(annotationContent);
133        Content tHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
134                HtmlStyle.title, contents.moduleLabel);
135        tHeading.addContent(Contents.SPACE);
136        Content moduleHead = new RawHtml(heading);
137        tHeading.addContent(moduleHead);
138        div.addContent(tHeading);
139        if (configuration.allowTag(HtmlTag.MAIN)) {
140            mainTree.addContent(div);
141        } else {
142            bodyTree.addContent(div);
143        }
144        return bodyTree;
145    }
146
147    /**
148     * Get the content header.
149     */
150    @Override
151    public Content getContentHeader() {
152        HtmlTree div = new HtmlTree(HtmlTag.DIV);
153        div.addStyle(HtmlStyle.contentContainer);
154        return div;
155    }
156
157    /**
158     * Get the summary section header.
159     */
160    @Override
161    public Content getSummaryHeader() {
162        HtmlTree li = new HtmlTree(HtmlTag.LI);
163        li.addStyle(HtmlStyle.blockList);
164        return li;
165    }
166
167    /**
168     * Get the summary tree.
169     *
170     * @param summaryContentTree the content tree to be added to the summary tree.
171     */
172    @Override
173    public Content getSummaryTree(Content summaryContentTree) {
174        HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, summaryContentTree);
175        return ul;
176    }
177
178    /**
179     * Generate the directive map for the directives on the module.
180     */
181    public void generateDirectiveMap() {
182        for (ModuleElement.Directive d : mdle.getDirectives()) {
183            if (directiveMap.containsKey(d.getKind())) {
184                List<ModuleElement.Directive> dir = directiveMap.get(d.getKind());
185                dir.add(d);
186                directiveMap.put(d.getKind(), dir);
187            } else {
188                List<ModuleElement.Directive> dir = new ArrayList<>();
189                dir.add(d);
190                directiveMap.put(d.getKind(), dir);
191            }
192        }
193    }
194
195    /**
196     * Add the summary header.
197     *
198     * @param startMarker the marker comment
199     * @param markerAnchor the marker anchor for the section
200     * @param heading the heading for the section
201     * @param htmltree the content tree to which the information is added
202     */
203    public void addSummaryHeader(Content startMarker, SectionName markerAnchor, Content heading, Content htmltree) {
204        htmltree.addContent(startMarker);
205        htmltree.addContent(getMarkerAnchor(markerAnchor));
206        htmltree.addContent(HtmlTree.HEADING(HtmlTag.H3, heading));
207    }
208
209    /**
210     * Add the summary for the module.
211     *
212     * @param text the table caption
213     * @param tableSummary the summary for the table
214     * @param htmltree the content tree to which the table will be added
215     * @param tableStyle the table style
216     * @param tableHeader the table header
217     * @param dirs the list of module directives
218     */
219    public void addSummary(String text, String tableSummary, Content htmltree, HtmlStyle tableStyle,
220            List<String> tableHeader, List<ModuleElement.Directive> dirs) {
221        Content table = (configuration.isOutputHtml5())
222                ? HtmlTree.TABLE(tableStyle, getTableCaption(new RawHtml(text)))
223                : HtmlTree.TABLE(tableStyle, tableSummary, getTableCaption(new RawHtml(text)));
224        table.addContent(getSummaryTableHeader(tableHeader, "col"));
225        Content tbody = new HtmlTree(HtmlTag.TBODY);
226        addList(dirs, tbody);
227        table.addContent(tbody);
228        htmltree.addContent(table);
229    }
230
231    /**
232     * Add the list of directives for the module.
233     *
234     * @param dirs the list of module directives
235     * @param tbody the content tree to which the list is added
236     */
237    public void addList(List<ModuleElement.Directive> dirs, Content tbody) {
238        boolean altColor = true;
239        for (ModuleElement.Directive direct : dirs) {
240            DirectiveKind kind = direct.getKind();
241            switch (kind) {
242                case REQUIRES:
243                    addRequiresList((ModuleElement.RequiresDirective) direct, tbody, altColor);
244                    break;
245                case EXPORTS:
246                    addExportedPackagesList((ModuleElement.ExportsDirective) direct, tbody, altColor);
247                    break;
248                case OPENS:
249                    //XXX ignore for now
250                    break;
251                case USES:
252                    addUsesList((ModuleElement.UsesDirective) direct, tbody, altColor);
253                    break;
254                case PROVIDES:
255                    addProvidesList((ModuleElement.ProvidesDirective) direct, tbody, altColor);
256                    break;
257                default:
258                    throw new AssertionError("unknown directive kind: " + kind);
259            }
260            altColor = !altColor;
261        }
262    }
263
264    /**
265     * {@inheritDoc}
266     */
267    @Override
268    public void addModulesSummary(Content summaryContentTree) {
269        List<ModuleElement.Directive> dirs = directiveMap.get(DirectiveKind.REQUIRES);
270        if (dirs != null && !dirs.isEmpty()) {
271            HtmlTree li = new HtmlTree(HtmlTag.LI);
272            li.addStyle(HtmlStyle.blockList);
273            addSummaryHeader(HtmlConstants.START_OF_MODULES_SUMMARY, SectionName.MODULES,
274                    contents.navModules, li);
275            String text = configuration.getText("doclet.Requires_Summary");
276            String tableSummary = configuration.getText("doclet.Member_Table_Summary",
277                    configuration.getText("doclet.Requires_Summary"),
278                    configuration.getText("doclet.modules"));
279            addRequiresSummary(text, tableSummary, dirs, li);
280            HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li);
281            summaryContentTree.addContent(ul);
282        }
283    }
284
285    /**
286     * Add the requires summary for the module.
287     *
288     * @param text the table caption
289     * @param tableSummary the summary for the table
290     * @param dirs the list of module directives
291     * @param htmltree the content tree to which the table will be added
292     */
293    public void addRequiresSummary(String text, String tableSummary, List<ModuleElement.Directive> dirs,
294            Content htmltree) {
295        addSummary(text, tableSummary, htmltree, HtmlStyle.requiresSummary, requiresTableHeader, dirs);
296    }
297
298    /**
299     * Add the requires directive list for the module.
300     *
301     * @param direct the requires directive
302     * @param tbody the content tree to which the directive will be added
303     * @param altColor true if altColor style should be used or false if rowColor style should be used
304     */
305    public void addRequiresList(ModuleElement.RequiresDirective direct, Content tbody, boolean altColor) {
306        ModuleElement m = direct.getDependency();
307        Content moduleLinkContent = getModuleLink(m, new StringContent(m.getQualifiedName().toString()));
308        Content thPackage = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, moduleLinkContent);
309        HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
310        tdSummary.addStyle(HtmlStyle.colLast);
311        addSummaryComment(m, tdSummary);
312        HtmlTree tr = HtmlTree.TR(thPackage);
313        tr.addContent(tdSummary);
314        tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
315        tbody.addContent(tr);
316    }
317
318    /**
319     * {@inheritDoc}
320     */
321    @Override
322    public void addPackagesSummary(Content summaryContentTree) {
323        List<ModuleElement.Directive> dirs = directiveMap.get(DirectiveKind.EXPORTS);
324        if (dirs != null && !dirs.isEmpty()) {
325            HtmlTree li = new HtmlTree(HtmlTag.LI);
326            li.addStyle(HtmlStyle.blockList);
327            addSummaryHeader(HtmlConstants.START_OF_PACKAGES_SUMMARY, SectionName.PACKAGES,
328                    contents.navPackages, li);
329            String text = configuration.getText("doclet.Exported_Packages_Summary");
330            String tableSummary = configuration.getText("doclet.Member_Table_Summary",
331                    configuration.getText("doclet.Exported_Packages_Summary"),
332                    configuration.getText("doclet.packages"));
333            addExportedPackagesSummary(text, tableSummary, dirs, li);
334            HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li);
335            summaryContentTree.addContent(ul);
336        }
337    }
338
339    /**
340     * Add the exported packages summary for the module.
341     *
342     * @param text the table caption
343     * @param tableSummary the summary for the table
344     * @param dirs the list of module directives
345     * @param htmltree the content tree to which the table will be added
346     */
347    public void addExportedPackagesSummary(String text, String tableSummary, List<ModuleElement.Directive> dirs,
348            Content htmltree) {
349        addSummary(text, tableSummary, htmltree, HtmlStyle.packagesSummary, exportedPackagesTableHeader, dirs);
350    }
351
352    /**
353     * Add the exported packages list for the module.
354     *
355     * @param direct the requires directive
356     * @param tbody the content tree to which the directive will be added
357     * @param altColor true if altColor style should be used or false if rowColor style should be used
358     */
359    public void addExportedPackagesList(ModuleElement.ExportsDirective direct, Content tbody, boolean altColor) {
360        PackageElement pkg = direct.getPackage();
361        Content pkgLinkContent = getPackageLink(pkg, new StringContent(utils.getPackageName(pkg)));
362        Content tdPackage = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, pkgLinkContent);
363        HtmlTree thModules = new HtmlTree(HtmlTag.TD);
364        thModules.addStyle(HtmlStyle.colSecond);
365        List<? extends ModuleElement> targetModules = direct.getTargetModules();
366        if (targetModules != null) {
367            List<? extends ModuleElement> mElements = direct.getTargetModules();
368            for (int i = 0; i < mElements.size(); i++) {
369                if (i > 0) {
370                    thModules.addContent(new HtmlTree(HtmlTag.BR));
371                }
372                ModuleElement m = mElements.get(i);
373                thModules.addContent(new StringContent(m.getQualifiedName().toString()));
374            }
375        } else {
376            thModules.addContent(configuration.getText("doclet.All_Modules"));
377        }
378        HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
379        tdSummary.addStyle(HtmlStyle.colLast);
380        addSummaryComment(pkg, tdSummary);
381        HtmlTree tr = HtmlTree.TR(tdPackage);
382        tr.addContent(thModules);
383        tr.addContent(tdSummary);
384        tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
385        tbody.addContent(tr);
386    }
387
388    /**
389     * {@inheritDoc}
390     */
391    @Override
392    public void addServicesSummary(Content summaryContentTree) {
393        List<ModuleElement.Directive> usesDirs = directiveMap.get(DirectiveKind.USES);
394        List<ModuleElement.Directive> providesDirs = directiveMap.get(DirectiveKind.PROVIDES);
395        if ((usesDirs != null && !usesDirs.isEmpty()) || (providesDirs != null && !providesDirs.isEmpty())) {
396            HtmlTree li = new HtmlTree(HtmlTag.LI);
397            li.addStyle(HtmlStyle.blockList);
398            addSummaryHeader(HtmlConstants.START_OF_SERVICES_SUMMARY, SectionName.SERVICES,
399                    contents.navServices, li);
400            String text;
401            String tableSummary;
402            if (usesDirs != null && !usesDirs.isEmpty()) {
403                text = configuration.getText("doclet.Uses_Summary");
404                tableSummary = configuration.getText("doclet.Member_Table_Summary",
405                        configuration.getText("doclet.Uses_Summary"),
406                        configuration.getText("doclet.types"));
407                addUsesSummary(text, tableSummary, usesDirs, li);
408            }
409            if (providesDirs != null && !providesDirs.isEmpty()) {
410                text = configuration.getText("doclet.Provides_Summary");
411                tableSummary = configuration.getText("doclet.Member_Table_Summary",
412                        configuration.getText("doclet.Provides_Summary"),
413                        configuration.getText("doclet.types"));
414                addProvidesSummary(text, tableSummary, providesDirs, li);
415            }
416            HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li);
417            summaryContentTree.addContent(ul);
418        }
419    }
420
421    /**
422     * Add the uses summary for the module.
423     *
424     * @param text the table caption
425     * @param tableSummary the summary for the table
426     * @param dirs the list of module directives
427     * @param htmltree the content tree to which the table will be added
428     */
429    public void addUsesSummary(String text, String tableSummary, List<ModuleElement.Directive> dirs,
430            Content htmltree) {
431        addSummary(text, tableSummary, htmltree, HtmlStyle.usesSummary, usesTableHeader, dirs);
432    }
433
434    /**
435     * Add the uses list for the module.
436     *
437     * @param direct the requires directive
438     * @param tbody the content tree to which the directive will be added
439     * @param altColor true if altColor style should be used or false if rowColor style should be used
440     */
441    public void addUsesList(ModuleElement.UsesDirective direct, Content tbody, boolean altColor) {
442        TypeElement type = direct.getService();
443        Content typeLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, type));
444        Content thPackage = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, typeLinkContent);
445        HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
446        tdSummary.addStyle(HtmlStyle.colLast);
447        addSummaryComment(type, tdSummary);
448        HtmlTree tr = HtmlTree.TR(thPackage);
449        tr.addContent(tdSummary);
450        tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
451        tbody.addContent(tr);
452    }
453
454    /**
455     * Add the provides summary for the module.
456     *
457     * @param text the table caption
458     * @param tableSummary the summary for the table
459     * @param dirs the list of module directives
460     * @param htmltree the content tree to which the table will be added
461     */
462    public void addProvidesSummary(String text, String tableSummary, List<ModuleElement.Directive> dirs,
463            Content htmltree) {
464        addSummary(text, tableSummary, htmltree, HtmlStyle.providesSummary, providesTableHeader, dirs);
465    }
466
467    /**
468     * Add the exported packages list for the module.
469     *
470     * @param direct the requires directive
471     * @param tbody the content tree to which the directive will be added
472     * @param altColor true if altColor style should be used or false if rowColor style should be used
473     */
474    public void addProvidesList(ModuleElement.ProvidesDirective direct, Content tbody, boolean altColor) {
475        List<? extends TypeElement> impls = direct.getImplementations();
476        for (TypeElement impl : impls) {
477            TypeElement srv = direct.getService();
478            Content implLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, impl));
479            Content srvLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, srv));
480            HtmlTree thType = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, srvLinkContent);
481            thType.addContent(new HtmlTree(HtmlTag.BR));
482            thType.addContent("(");
483            HtmlTree implSpan = HtmlTree.SPAN(HtmlStyle.implementationLabel, contents.implementation);
484            thType.addContent(implSpan);
485            thType.addContent(Contents.SPACE);
486            thType.addContent(implLinkContent);
487            thType.addContent(")");
488            HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
489            tdDesc.addStyle(HtmlStyle.colLast);
490            addSummaryComment(srv, tdDesc);
491            HtmlTree tr = HtmlTree.TR(thType);
492            tr.addContent(tdDesc);
493            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
494            tbody.addContent(tr);
495        }
496    }
497
498    /**
499     * Add the module deprecation information to the documentation tree.
500     *
501     * @param div the content tree to which the deprecation information will be added
502     */
503    public void addDeprecationInfo(Content div) {
504        List<? extends DocTree> deprs = utils.getBlockTags(mdle, DocTree.Kind.DEPRECATED);
505        if (utils.isDeprecated(mdle)) {
506            CommentHelper ch = utils.getCommentHelper(mdle);
507            HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
508            deprDiv.addStyle(HtmlStyle.deprecatedContent);
509            Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, contents.deprecatedPhrase);
510            deprDiv.addContent(deprPhrase);
511            if (!deprs.isEmpty()) {
512                List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
513                if (!commentTags.isEmpty()) {
514                    addInlineDeprecatedComment(mdle, deprs.get(0), deprDiv);
515                }
516            }
517            div.addContent(deprDiv);
518        }
519    }
520
521    /**
522     * {@inheritDoc}
523     */
524    @Override
525    public void addModuleDescription(Content moduleContentTree) {
526        if (!utils.getFullBody(mdle).isEmpty()) {
527            Content tree = configuration.allowTag(HtmlTag.SECTION) ? HtmlTree.SECTION() : moduleContentTree;
528            addDeprecationInfo(tree);
529            tree.addContent(HtmlConstants.START_OF_MODULE_DESCRIPTION);
530            tree.addContent(getMarkerAnchor(SectionName.MODULE_DESCRIPTION));
531            addInlineComment(mdle, tree);
532            if (configuration.allowTag(HtmlTag.SECTION)) {
533                moduleContentTree.addContent(tree);
534            }
535        }
536    }
537
538    /**
539     * {@inheritDoc}
540     */
541    @Override
542    public void addModuleTags(Content moduleContentTree) {
543        Content tree = (configuration.allowTag(HtmlTag.SECTION))
544                ? HtmlTree.SECTION()
545                : moduleContentTree;
546        addTagsInfo(mdle, tree);
547        if (configuration.allowTag(HtmlTag.SECTION)) {
548            moduleContentTree.addContent(tree);
549        }
550    }
551
552    /**
553     * Add summary details to the navigation bar.
554     *
555     * @param subDiv the content tree to which the summary detail links will be added
556     */
557    @Override
558    protected void addSummaryDetailLinks(Content subDiv) {
559        Content div = HtmlTree.DIV(getNavSummaryLinks());
560        subDiv.addContent(div);
561    }
562
563    /**
564     * Get summary links for navigation bar.
565     *
566     * @return the content tree for the navigation summary links
567     */
568    protected Content getNavSummaryLinks() {
569        Content li = HtmlTree.LI(contents.moduleSubNavLabel);
570        li.addContent(Contents.SPACE);
571        Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li);
572        Content liNav = new HtmlTree(HtmlTag.LI);
573        liNav.addContent(!utils.getFullBody(mdle).isEmpty() && !configuration.nocomment
574                ? getHyperLink(SectionName.MODULE_DESCRIPTION, contents.navModuleDescription)
575                : contents.navModuleDescription);
576        addNavGap(liNav);
577        liNav.addContent(showDirectives(DirectiveKind.REQUIRES)
578                ? getHyperLink(SectionName.MODULES, contents.navModules)
579                : contents.navModules);
580        addNavGap(liNav);
581        liNav.addContent(showDirectives(DirectiveKind.EXPORTS)
582                ? getHyperLink(SectionName.PACKAGES, contents.navPackages)
583                : contents.navPackages);
584        addNavGap(liNav);
585        liNav.addContent((showDirectives(DirectiveKind.USES) || showDirectives(DirectiveKind.PROVIDES))
586                ? getHyperLink(SectionName.SERVICES, contents.navServices)
587                : contents.navServices);
588        ulNav.addContent(liNav);
589        return ulNav;
590    }
591
592    /**
593     * Return true if the directive should be displayed.
594     *
595     * @param dirKind the kind of directive for the module
596     * @return true if the directive should be displayed
597     */
598    private boolean showDirectives(DirectiveKind dirKind) {
599        return directiveMap.get(dirKind) != null && !directiveMap.get(dirKind).isEmpty();
600    }
601
602    /**
603     * {@inheritDoc}
604     */
605    @Override
606    public void addModuleContent(Content contentTree, Content moduleContentTree) {
607        if (configuration.allowTag(HtmlTag.MAIN)) {
608            mainTree.addContent(moduleContentTree);
609            contentTree.addContent(mainTree);
610        } else {
611            contentTree.addContent(moduleContentTree);
612        }
613    }
614
615    /**
616     * {@inheritDoc}
617     */
618    @Override
619    public void addModuleFooter(Content contentTree) {
620        Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
621                ? HtmlTree.FOOTER()
622                : contentTree;
623        addNavLinks(false, htmlTree);
624        addBottom(htmlTree);
625        if (configuration.allowTag(HtmlTag.FOOTER)) {
626            contentTree.addContent(htmlTree);
627        }
628    }
629
630    /**
631     * {@inheritDoc}
632     */
633    @Override
634    public void printDocument(Content contentTree) throws DocFileIOException {
635        printHtmlDocument(configuration.metakeywords.getMetaKeywordsForModule(mdle),
636                true, contentTree);
637    }
638
639    /**
640     * Add the module package deprecation information to the documentation tree.
641     *
642     * @param li the content tree to which the deprecation information will be added
643     * @param pkg the PackageDoc that is added
644     */
645    public void addPackageDeprecationInfo(Content li, PackageElement pkg) {
646        List<? extends DocTree> deprs;
647        if (utils.isDeprecated(pkg)) {
648            deprs = utils.getDeprecatedTrees(pkg);
649            HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
650            deprDiv.addStyle(HtmlStyle.deprecatedContent);
651            Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, contents.deprecatedPhrase);
652            deprDiv.addContent(deprPhrase);
653            if (!deprs.isEmpty()) {
654                CommentHelper ch = utils.getCommentHelper(pkg);
655                List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
656                if (!commentTags.isEmpty()) {
657                    addInlineDeprecatedComment(pkg, deprs.get(0), deprDiv);
658                }
659            }
660            li.addContent(deprDiv);
661        }
662    }
663
664    /**
665     * Get this module link.
666     *
667     * @return a content tree for the module link
668     */
669    @Override
670    protected Content getNavLinkModule() {
671        Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, contents.moduleLabel);
672        return li;
673    }
674
675    /**
676     * Get "PREV MODULE" link in the navigation bar.
677     *
678     * @return a content tree for the previous link
679     */
680    @Override
681    public Content getNavLinkPrevious() {
682        Content li;
683        if (prevModule == null) {
684            li = HtmlTree.LI(contents.prevModuleLabel);
685        } else {
686            li = HtmlTree.LI(getHyperLink(pathToRoot.resolve(DocPaths.moduleSummary(
687                    prevModule)), contents.prevModuleLabel, "", ""));
688        }
689        return li;
690    }
691
692    /**
693     * Get "NEXT MODULE" link in the navigation bar.
694     *
695     * @return a content tree for the next link
696     */
697    @Override
698    public Content getNavLinkNext() {
699        Content li;
700        if (nextModule == null) {
701            li = HtmlTree.LI(contents.nextModuleLabel);
702        } else {
703            li = HtmlTree.LI(getHyperLink(pathToRoot.resolve(DocPaths.moduleSummary(
704                    nextModule)), contents.nextModuleLabel, "", ""));
705        }
706        return li;
707    }
708}
709