Skip to content

Commit cfe719f

Browse files
committed
8340565: Create separate index page for terms defined by the index tag
Reviewed-by: prappo
1 parent baabfbb commit cfe719f

File tree

13 files changed

+370
-168
lines changed

13 files changed

+370
-168
lines changed

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ public class Contents {
172172
public final Content relatedPackages;
173173
public final Content returns;
174174
public final Content searchLabel;
175+
public final Content searchTagsLabel;
175176
public final Content seeAlso;
176177
public final Content serializedForm;
177178
public final Content servicesLabel;
@@ -325,6 +326,7 @@ public class Contents {
325326
relatedPackages = getContent("doclet.Related_Packages");
326327
returns = getContent("doclet.Returns");
327328
searchLabel = getContent("doclet.search");
329+
searchTagsLabel = getContent("doclet.searchTags");
328330
seeAlso = getContent("doclet.See_Also");
329331
serializedForm = getContent("doclet.Serialized_Form");
330332
servicesLabel = getContent("doclet.Services");

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ private Content getNavigationSection() {
183183
* <li>Declaration pages: module, package, classes
184184
* <li>Derived info for declarations: use and tree
185185
* <li>General summary info: deprecated, preview
186-
* <li>Detailed summary info: constant values, serialized form, system properties
186+
* <li>Detailed summary info: constant values, search tags, serialized form, system properties
187187
* <li>Index info: all packages, all classes, full index
188188
* </ul>
189189
*
@@ -346,6 +346,15 @@ private Content getPageKindSection() {
346346
pageKindsSection.add(section);
347347
}
348348

349+
// Search Tags
350+
if (configuration.conditionalPages.contains(HtmlConfiguration.ConditionalPage.SEARCH_TAGS)) {
351+
section = newHelpSection(contents.searchTagsLabel, PageMode.SEARCH_TAGS);
352+
Content searchTagsBody = getContent("doclet.help.searchTags.body",
353+
links.createLink(DocPaths.SEARCH_TAGS, resources.getText("doclet.searchTags")));
354+
section.add(HtmlTree.P(searchTagsBody));
355+
pageKindsSection.add(section);
356+
}
357+
349358
// Serialized Form
350359
if (configuration.conditionalPages.contains(HtmlConfiguration.ConditionalPage.SERIALIZED_FORM)) {
351360
section = newHelpSection(contents.serializedForm, PageMode.SERIALIZED_FORM)

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ public class HtmlConfiguration extends BaseConfiguration {
177177
// which performs a somewhat similar role
178178
public enum ConditionalPage {
179179
CONSTANT_VALUES, DEPRECATED, EXTERNAL_SPECS, PREVIEW, RESTRICTED,
180-
SERIALIZED_FORM, SYSTEM_PROPERTIES, NEW
180+
SEARCH_TAGS, SERIALIZED_FORM, SYSTEM_PROPERTIES, NEW
181181
}
182182

183183
/**

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ protected void generateOtherFiles(ClassTree classTree)
283283
if (!options.noExternalSpecsPage()){
284284
writerFactory.newExternalSpecsWriter().buildPage();
285285
}
286+
writerFactory.newSearchTagsWriter().buildPage();
286287
writerFactory.newSystemPropertiesWriter().buildPage();
287288

288289
configuration.indexBuilder.addElements();
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
/*
2+
* Copyright (c) 2019, 2024, 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+
26+
package jdk.javadoc.internal.doclets.formats.html;
27+
28+
import java.nio.file.Path;
29+
import java.util.ArrayList;
30+
import java.util.List;
31+
import java.util.Locale;
32+
import java.util.Map;
33+
import java.util.Objects;
34+
import java.util.TreeMap;
35+
import java.util.WeakHashMap;
36+
import java.util.stream.Collectors;
37+
38+
import com.sun.source.doctree.DocTree;
39+
40+
import jdk.javadoc.internal.doclets.formats.html.Navigation.PageMode;
41+
import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
42+
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyles;
43+
import jdk.javadoc.internal.doclets.toolkit.DocFileElement;
44+
import jdk.javadoc.internal.doclets.toolkit.OverviewElement;
45+
import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
46+
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
47+
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
48+
import jdk.javadoc.internal.doclets.toolkit.util.IndexItem;
49+
import jdk.javadoc.internal.html.Content;
50+
import jdk.javadoc.internal.html.ContentBuilder;
51+
import jdk.javadoc.internal.html.HtmlTree;
52+
import jdk.javadoc.internal.html.Text;
53+
54+
import static java.util.stream.Collectors.groupingBy;
55+
56+
/**
57+
* Generates summary files for tags represented by {@code IndexItem}.
58+
* Supported items are search tags and system properties.
59+
*/
60+
public abstract class IndexItemListWriter extends HtmlDocletWriter {
61+
62+
/**
63+
* Cached contents of {@code <title>...</title>} tags of the HTML pages.
64+
*/
65+
final Map<DocFileElement, String> titles = new WeakHashMap<>();
66+
67+
/**
68+
* Constructs a IndexItemListWriter object.
69+
*
70+
* @param configuration The current configuration
71+
* @param path the doc path of the file to write
72+
*/
73+
protected IndexItemListWriter(HtmlConfiguration configuration, DocPath path) {
74+
super(configuration, path, false);
75+
}
76+
77+
@Override
78+
public void buildPage() throws DocFileIOException {
79+
boolean hasTags = configuration.indexBuilder != null
80+
&& !configuration.indexBuilder.getItems(getKind()).isEmpty();
81+
if (!hasTags) {
82+
return;
83+
}
84+
85+
writeGenerating();
86+
configuration.conditionalPages.add(getConditionalPage());
87+
88+
String title = getPageLabel().toString();
89+
HtmlTree body = getBody(getWindowTitle(title));
90+
Content mainContent = new ContentBuilder();
91+
addIndexItems(mainContent);
92+
body.add(new BodyContents()
93+
.setHeader(getHeader(getPageMode()))
94+
.addMainContent(HtmlTree.DIV(HtmlStyles.header,
95+
HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, getPageLabel())))
96+
.addMainContent(mainContent)
97+
.setFooter(getFooter()));
98+
printHtmlDocument(null, title.toLowerCase(Locale.ROOT), body);
99+
100+
if (configuration.indexBuilder != null) {
101+
configuration.indexBuilder.add(IndexItem.of(IndexItem.Category.TAGS, title, path));
102+
}
103+
}
104+
105+
protected Map<String, List<IndexItem>> groupTags() {
106+
return configuration.indexBuilder.getItems(getKind()).stream()
107+
.collect(groupingBy(IndexItem::getLabel, TreeMap::new, Collectors.toCollection(ArrayList::new)));
108+
}
109+
110+
protected Content createLink(IndexItem i) {
111+
assert i.getDocTree().getKind() == getKind() : i;
112+
var element = i.getElement();
113+
if (element instanceof OverviewElement) {
114+
return links.createLink(pathToRoot.resolve(i.getUrl()),
115+
resources.getText("doclet.Overview"));
116+
} else if (element instanceof DocFileElement e) {
117+
var fo = e.getFileObject();
118+
var t = titles.computeIfAbsent(e, this::getFileTitle);
119+
if (t.isBlank()) {
120+
// The user should probably be notified (a warning?) that this
121+
// file does not have a title
122+
var p = Path.of(fo.toUri());
123+
t = p.getFileName().toString();
124+
}
125+
var b = new ContentBuilder()
126+
.add(HtmlTree.CODE(Text.of(i.getHolder() + ": ")))
127+
.add(t);
128+
return links.createLink(pathToRoot.resolve(i.getUrl()), b);
129+
} else {
130+
// program elements should be displayed using a code font
131+
var link = links.createLink(pathToRoot.resolve(i.getUrl()), i.getHolder());
132+
return HtmlTree.CODE(link);
133+
}
134+
}
135+
136+
/**
137+
* Adds a table with the included index items to the content.
138+
*
139+
* @param target the content to which the table will be added
140+
*/
141+
protected abstract void addIndexItems(Content target);
142+
143+
/**
144+
* {@return the kind of index item to list in this page}
145+
*/
146+
protected abstract DocTree.Kind getKind();
147+
148+
/**
149+
* {@return the conditional page value}
150+
*/
151+
protected abstract HtmlConfiguration.ConditionalPage getConditionalPage();
152+
153+
/**
154+
* {@return the label for the page heading}
155+
*/
156+
protected abstract Content getPageLabel();
157+
158+
/**
159+
* {@return the Navigation.PageMode value}
160+
*/
161+
protected abstract Navigation.PageMode getPageMode();
162+
163+
// Note: The reason we can't use anonymous classes below is that HtmlDocletWriter.getBodyStyle()
164+
// uses the writer's class name to deduce the CSS body style name.
165+
166+
public static IndexItemListWriter createSystemPropertiesWriter(HtmlConfiguration configuration) {
167+
return new SystemPropertiesWriter(configuration);
168+
}
169+
170+
public static IndexItemListWriter createSearchTagsWriter(HtmlConfiguration configuration) {
171+
return new SearchTagsWriter(configuration);
172+
}
173+
174+
static class SystemPropertiesWriter extends IndexItemListWriter {
175+
SystemPropertiesWriter(HtmlConfiguration configuration) {
176+
super(configuration, DocPaths.SYSTEM_PROPERTIES);
177+
}
178+
179+
@Override
180+
protected DocTree.Kind getKind() {
181+
return DocTree.Kind.SYSTEM_PROPERTY;
182+
}
183+
184+
@Override
185+
protected HtmlConfiguration.ConditionalPage getConditionalPage() {
186+
return HtmlConfiguration.ConditionalPage.SYSTEM_PROPERTIES;
187+
}
188+
189+
@Override
190+
protected Content getPageLabel() {
191+
return contents.systemPropertiesLabel;
192+
}
193+
194+
@Override
195+
protected Navigation.PageMode getPageMode() {
196+
return PageMode.SYSTEM_PROPERTIES;
197+
}
198+
199+
/**
200+
* Creates a 2-column table containing system properties.
201+
*
202+
* @param target the content to which the links will be added
203+
*/
204+
@Override
205+
protected void addIndexItems(Content target) {
206+
Map<String, List<IndexItem>> searchIndexMap = groupTags();
207+
Content separator = Text.of(", ");
208+
var table = new Table<Void>(HtmlStyles.summaryTable)
209+
.setCaption(contents.systemPropertiesSummaryLabel)
210+
.setHeader(new TableHeader(contents.propertyLabel, contents.referencedIn))
211+
.setColumnStyles(HtmlStyles.colFirst, HtmlStyles.colLast);
212+
searchIndexMap.forEach((key, searchIndexItems) -> {
213+
Content propertyName = Text.of(key);
214+
Content referenceLinks = new ContentBuilder();
215+
for (IndexItem searchIndexItem : searchIndexItems) {
216+
if (!referenceLinks.isEmpty()) {
217+
referenceLinks.add(separator);
218+
}
219+
referenceLinks.add(createLink(searchIndexItem));
220+
}
221+
table.addRow(propertyName, HtmlTree.DIV(HtmlStyles.block, referenceLinks));
222+
});
223+
target.add(table);
224+
}
225+
}
226+
227+
static class SearchTagsWriter extends IndexItemListWriter {
228+
SearchTagsWriter(HtmlConfiguration configuration) {
229+
super(configuration, DocPaths.SEARCH_TAGS);
230+
}
231+
232+
@Override
233+
protected DocTree.Kind getKind() {
234+
return DocTree.Kind.INDEX;
235+
}
236+
237+
@Override
238+
protected HtmlConfiguration.ConditionalPage getConditionalPage() {
239+
return HtmlConfiguration.ConditionalPage.SEARCH_TAGS;
240+
}
241+
242+
@Override
243+
protected Content getPageLabel() {
244+
return contents.searchTagsLabel;
245+
}
246+
247+
@Override
248+
protected Navigation.PageMode getPageMode() {
249+
return PageMode.SEARCH_TAGS;
250+
}
251+
252+
/**
253+
* Creates a 3-column table containing search tags.
254+
*
255+
* @param target the content to which the links will be added
256+
*/
257+
@Override
258+
protected void addIndexItems(Content target) {
259+
Map<String, List<IndexItem>> searchIndexMap = groupTags();
260+
Content separator = Text.of(", ");
261+
var table = new Table<Void>(HtmlStyles.summaryTable)
262+
.setCaption(contents.getContent("doclet.searchTagsSummary"))
263+
.setHeader(new TableHeader(contents.getContent("doclet.searchTag"),
264+
contents.descriptionLabel,
265+
contents.getContent("doclet.DefinedIn")))
266+
.setColumnStyles(HtmlStyles.colFirst, HtmlStyles.colSecond, HtmlStyles.colLast);
267+
searchIndexMap.forEach((key, searchIndexItems) -> {
268+
Content propertyName = Text.of(key);
269+
Content referenceLinks = new ContentBuilder();
270+
String description = "";
271+
for (IndexItem searchIndexItem : searchIndexItems) {
272+
if (!referenceLinks.isEmpty()) {
273+
referenceLinks.add(separator);
274+
}
275+
referenceLinks.add(createLink(searchIndexItem));
276+
if (description.isEmpty()) {
277+
description = searchIndexItem.getDescription();
278+
Objects.requireNonNull(description);
279+
}
280+
}
281+
table.addRow(propertyName, Text.of(description), HtmlTree.DIV(HtmlStyles.block, referenceLinks));
282+
});
283+
target.add(table);
284+
}
285+
}
286+
}

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,9 @@ public enum PageMode {
8787
PACKAGE,
8888
PREVIEW,
8989
RESTRICTED,
90-
SERIALIZED_FORM,
9190
SEARCH,
91+
SEARCH_TAGS,
92+
SERIALIZED_FORM,
9293
SYSTEM_PROPERTIES,
9394
TREE,
9495
USE
@@ -274,6 +275,7 @@ private void addMainNavLinks(Content target) {
274275
case CONSTANT_VALUES:
275276
case EXTERNAL_SPECS:
276277
case RESTRICTED:
278+
case SEARCH_TAGS:
277279
case SERIALIZED_FORM:
278280
case SYSTEM_PROPERTIES:
279281
addOverviewLink(target);

0 commit comments

Comments
 (0)