Skip to content

Commit 5a1e91d

Browse files
committed
Address PR comments
1 parent ac222ce commit 5a1e91d

File tree

11 files changed

+746
-293
lines changed

11 files changed

+746
-293
lines changed

codegen/src/main/java/software/amazon/awssdk/codegen/docs/OperationDocProvider.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@
1515

1616
package software.amazon.awssdk.codegen.docs;
1717

18+
import static software.amazon.awssdk.codegen.internal.Constant.EXAMPLE_META_PATH;
1819
import static software.amazon.awssdk.codegen.internal.DocumentationUtils.createLinkToServiceDocumentation;
1920
import static software.amazon.awssdk.codegen.internal.DocumentationUtils.stripHtmlTags;
2021

2122
import com.squareup.javapoet.ClassName;
2223
import java.util.Collections;
2324
import java.util.List;
25+
import java.util.Optional;
2426
import java.util.stream.Collectors;
25-
import software.amazon.awssdk.codegen.internal.DocumentationUtils;
27+
import software.amazon.awssdk.codegen.internal.ExampleMetadataProvider;
2628
import software.amazon.awssdk.codegen.model.intermediate.DocumentationModel;
2729
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
2830
import software.amazon.awssdk.codegen.model.intermediate.OperationModel;
@@ -88,13 +90,10 @@ String getDocs() {
8890
docBuilder.see(crosslink);
8991
}
9092

91-
String exampleMetaPath = "software/amazon/awssdk/codegen/example-meta.json";
92-
String codeExampleLink = DocumentationUtils.createLinkToCodeExample(model.getMetadata(),
93-
opModel.getOperationName(),
94-
exampleMetaPath);
95-
if (!codeExampleLink.isEmpty()) {
96-
docBuilder.see(codeExampleLink);
97-
}
93+
ExampleMetadataProvider exampleProvider = ExampleMetadataProvider.getInstance(EXAMPLE_META_PATH);
94+
Optional<String> codeExampleLink = exampleProvider.createLinkToCodeExample(model.getMetadata(),
95+
opModel.getOperationName());
96+
codeExampleLink.ifPresent(docBuilder::see);
9897
return docBuilder.build().replace("$", "&#36");
9998
}
10099

codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/PackageInfoGeneratorTasks.java

Lines changed: 136 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,41 @@
1515

1616
package software.amazon.awssdk.codegen.emitters.tasks;
1717

18+
import static software.amazon.awssdk.codegen.internal.Constant.EXAMPLE_META_PATH;
19+
1820
import java.util.Collections;
21+
import java.util.LinkedHashMap;
1922
import java.util.List;
2023
import java.util.Map;
24+
import java.util.stream.Collectors;
2125
import software.amazon.awssdk.codegen.emitters.GeneratorTask;
2226
import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams;
2327
import software.amazon.awssdk.codegen.emitters.SimpleGeneratorTask;
24-
import software.amazon.awssdk.codegen.internal.DocumentationUtils;
28+
import software.amazon.awssdk.codegen.internal.ExampleMetadataProvider;
2529
import software.amazon.awssdk.codegen.model.intermediate.Metadata;
2630

2731
/**
2832
* Emits the package-info.java for the base service package. Includes the service
29-
* level documentation.
33+
* level documentation and code examples for that service organized by category.
3034
*/
3135
public final class PackageInfoGeneratorTasks extends BaseGeneratorTasks {
3236

37+
/**
38+
* Mapping from internal category names to user-friendly display names.
39+
* This defines the preferred order and display format for code example categories.
40+
*/
41+
private static final Map<String, String> CATEGORY_DISPLAY_MAPPING;
42+
43+
static {
44+
Map<String, String> mapping = new LinkedHashMap<>();
45+
mapping.put("Hello", "Getting Started");
46+
mapping.put("Basics", "Basics");
47+
mapping.put("Api", "API Actions");
48+
mapping.put("Scenarios", "Scenarios");
49+
mapping.put("Serverless examples", "Serverless Examples");
50+
CATEGORY_DISPLAY_MAPPING = Collections.unmodifiableMap(mapping);
51+
}
52+
3353
private final String baseDirectory;
3454

3555
PackageInfoGeneratorTasks(GeneratorTaskParams dependencies) {
@@ -40,100 +60,150 @@ public final class PackageInfoGeneratorTasks extends BaseGeneratorTasks {
4060
@Override
4161
protected List<GeneratorTask> createTasks() throws Exception {
4262
Metadata metadata = model.getMetadata();
43-
44-
String baseDocumentation = metadata.getDocumentation();
45-
46-
String codeExamples = getCodeExamples(metadata);
63+
String packageInfoContents = buildPackageInfoContent(metadata, EXAMPLE_META_PATH);
4764

48-
StringBuilder sb = new StringBuilder();
49-
sb.append(String.format("/**%n * %s%n", baseDocumentation));
50-
if (!codeExamples.isEmpty()) {
51-
sb.append(String.format(" *%n * %s%n", codeExamples));
52-
}
53-
sb.append(String.format("*/%npackage %s;", metadata.getFullClientPackageName()));
54-
String packageInfoContents = sb.toString();
5565
return Collections.singletonList(new SimpleGeneratorTask(baseDirectory,
5666
"package-info.java",
5767
model.getFileHeader(),
5868
() -> packageInfoContents));
5969
}
6070

61-
String getCodeExamples(Metadata metadata) {
62-
String exampleMetaPath = "software/amazon/awssdk/codegen/example-meta.json";
63-
List<DocumentationUtils.ExampleData> examples =
64-
DocumentationUtils.getServiceCodeExamples(metadata, exampleMetaPath);
71+
/**
72+
* Builds the complete package-info.java content including Javadoc and package declaration.
73+
*
74+
* @param metadata the service metadata containing documentation and package information
75+
* @param exampleMetaPath the path to the example metadata JSON file
76+
* @return the complete package-info.java file content
77+
*/
78+
String buildPackageInfoContent(Metadata metadata, String exampleMetaPath) {
79+
String baseDocumentation = metadata.getDocumentation();
80+
String codeExamples = getCodeExamplesWithPath(metadata, exampleMetaPath);
81+
String javadocContent = buildJavadocContent(baseDocumentation, codeExamples);
82+
83+
return javadocContent + System.lineSeparator() + "package " + metadata.getFullClientPackageName() + ";";
84+
}
85+
86+
/**
87+
* Builds the Javadoc comment content for the package-info.java file.
88+
*
89+
* @param baseDocumentation the base service documentation
90+
* @param codeExamples the formatted code examples content, or empty string if none
91+
* @return the complete Javadoc comment including opening and closing markers
92+
*/
93+
private String buildJavadocContent(String baseDocumentation, String codeExamples) {
94+
StringBuilder javadoc = new StringBuilder();
95+
javadoc.append("/**").append(System.lineSeparator());
96+
javadoc.append(" * ").append(baseDocumentation).append(System.lineSeparator());
97+
98+
if (!codeExamples.isEmpty()) {
99+
javadoc.append(" *").append(System.lineSeparator());
100+
javadoc.append(" * ").append(codeExamples).append(System.lineSeparator());
101+
}
102+
103+
javadoc.append(" */");
104+
return javadoc.toString();
105+
}
106+
107+
/**
108+
* Gets code examples using a custom example metadata path.
109+
*/
110+
private String getCodeExamplesWithPath(Metadata metadata, String exampleMetaPath) {
111+
ExampleMetadataProvider exampleProvider = ExampleMetadataProvider.getInstance(exampleMetaPath);
112+
List<ExampleMetadataProvider.ExampleData> examples = exampleProvider.getServiceCodeExamples(metadata);
65113

66114
if (examples.isEmpty()) {
67115
return "";
68116
}
69117

70-
String codeExamplesJavadoc = generateCodeExamplesJavadoc(examples);
118+
return generateCodeExamplesJavadoc(examples);
119+
}
71120

121+
private String generateCodeExamplesJavadoc(List<ExampleMetadataProvider.ExampleData> examples) {
122+
Map<String, List<ExampleMetadataProvider.ExampleData>> categorizedExamples =
123+
examples.stream().collect(Collectors.groupingBy(ExampleMetadataProvider.ExampleData::getCategory,
124+
LinkedHashMap::new,
125+
Collectors.toList()));
126+
127+
StringBuilder javadoc = new StringBuilder();
128+
javadoc.append("<h2>Code Examples</h2>").append(System.lineSeparator());
129+
javadoc.append("<p>The following code examples show how to use this service with the AWS SDK for Java v2:</p>")
130+
.append(System.lineSeparator());
131+
132+
appendPredefinedCategories(javadoc, categorizedExamples, CATEGORY_DISPLAY_MAPPING);
133+
appendRemainingCategories(javadoc, categorizedExamples, CATEGORY_DISPLAY_MAPPING);
134+
135+
return formatAsJavadocLines(javadoc.toString());
136+
}
137+
138+
/**
139+
* Formats HTML content as properly indented Javadoc comment lines.
140+
* Each non-empty line gets prefixed with appropriate Javadoc comment formatting.
141+
*
142+
* @param htmlContent the HTML content to format for Javadoc
143+
* @return formatted string ready for inclusion in Javadoc comments
144+
*/
145+
private String formatAsJavadocLines(String htmlContent) {
72146
StringBuilder result = new StringBuilder();
73-
String[] lines = codeExamplesJavadoc.split("\n");
74-
for (String line : lines) {
147+
String[] lines = htmlContent.split(System.lineSeparator());
148+
149+
for (int i = 0; i < lines.length; i++) {
150+
String line = lines[i];
75151
if (!line.trim().isEmpty()) {
76152
result.append(line);
77-
if (!line.equals(lines[lines.length - 1])) {
153+
if (i < lines.length - 1) {
78154
result.append(System.lineSeparator()).append(" * ");
79155
}
80156
}
81157
}
82-
83158
return result.toString();
84159
}
85-
86160

87-
private String generateCodeExamplesJavadoc(List<DocumentationUtils.ExampleData> examples) {
88-
Map<String, List<DocumentationUtils.ExampleData>> categorizedExamples = new java.util.LinkedHashMap<>();
89-
for (DocumentationUtils.ExampleData example : examples) {
90-
categorizedExamples.computeIfAbsent(example.getCategory(), k -> new java.util.ArrayList<>()).add(example);
91-
}
92-
93-
StringBuilder javadoc = new StringBuilder();
94-
javadoc.append("<h2>Code Examples</h2>").append("\n");
95-
javadoc.append("<p>The following code examples show how to use this service with the AWS SDK for Java v2:</p>")
96-
.append("\n");
97-
98-
Map<String, String> categoryMapping = new java.util.LinkedHashMap<>();
99-
categoryMapping.put("Hello", "Getting Started");
100-
categoryMapping.put("Basics", "Basics");
101-
categoryMapping.put("Api", "API Actions");
102-
categoryMapping.put("Scenarios", "Scenarios");
103-
categoryMapping.put("Serverless examples", "Serverless Examples");
104-
105-
for (Map.Entry<String, String> entry : categoryMapping.entrySet()) {
106-
String category = entry.getKey();
107-
String displayName = entry.getValue();
108-
List<DocumentationUtils.ExampleData> categoryExamples = categorizedExamples.get(category);
109-
if (categoryExamples != null && !categoryExamples.isEmpty()) {
110-
appendCategorySection(javadoc, displayName, categoryExamples);
111-
}
112-
}
161+
/**
162+
* Appends predefined categories to the Javadoc in the preferred order.
163+
* Only includes categories that exist in the categorized examples and have content.
164+
*/
165+
private void appendPredefinedCategories(StringBuilder javadoc,
166+
Map<String, List<ExampleMetadataProvider.ExampleData>> categorizedExamples,
167+
Map<String, String> categoryMapping) {
168+
categoryMapping.forEach((category, displayName) ->
169+
appendCategoryIfExists(javadoc, categorizedExamples, category, displayName));
170+
}
113171

114-
for (Map.Entry<String, List<DocumentationUtils.ExampleData>> entry : categorizedExamples.entrySet()) {
115-
String category = entry.getKey();
116-
if (!categoryMapping.containsKey(category)) {
117-
List<DocumentationUtils.ExampleData> categoryExamples = entry.getValue();
118-
if (!categoryExamples.isEmpty()) {
119-
appendCategorySection(javadoc, category, categoryExamples);
120-
}
121-
}
172+
/**
173+
* Appends any remaining categories that weren't in the predefined mapping.
174+
*/
175+
private void appendRemainingCategories(StringBuilder javadoc,
176+
Map<String, List<ExampleMetadataProvider.ExampleData>> categorizedExamples,
177+
Map<String, String> categoryMapping) {
178+
categorizedExamples.entrySet().stream()
179+
.filter(entry -> !categoryMapping.containsKey(entry.getKey()))
180+
.forEach(entry -> appendCategoryIfExists(javadoc, categorizedExamples, entry.getKey(),
181+
entry.getKey()));
182+
}
183+
184+
/**
185+
* Appends a category section if examples exist for the given category.
186+
*/
187+
private void appendCategoryIfExists(StringBuilder javadoc,
188+
Map<String, List<ExampleMetadataProvider.ExampleData>> categorizedExamples,
189+
String category,
190+
String displayName) {
191+
List<ExampleMetadataProvider.ExampleData> categoryExamples = categorizedExamples.get(category);
192+
if (categoryExamples != null && !categoryExamples.isEmpty()) {
193+
appendCategorySection(javadoc, displayName, categoryExamples);
122194
}
123-
124-
return javadoc.toString();
125195
}
126196

127197
private void appendCategorySection(StringBuilder javadoc, String displayName,
128-
List<DocumentationUtils.ExampleData> categoryExamples) {
129-
javadoc.append("<h3>").append(displayName).append("</h3>").append("\n");
130-
javadoc.append("<ul>").append("\n");
131-
132-
for (DocumentationUtils.ExampleData example : categoryExamples) {
198+
List<ExampleMetadataProvider.ExampleData> categoryExamples) {
199+
javadoc.append("<h3>").append(displayName).append("</h3>").append(System.lineSeparator());
200+
javadoc.append("<ul>").append(System.lineSeparator());
201+
202+
for (ExampleMetadataProvider.ExampleData example : categoryExamples) {
133203
javadoc.append("<li><a href=\"").append(example.getUrl()).append("\" target=\"_top\">")
134-
.append(example.getTitle()).append("</a></li>").append("\n");
204+
.append(example.getTitle()).append("</a></li>").append(System.lineSeparator());
135205
}
136-
javadoc.append("</ul>").append("\n");
206+
javadoc.append("</ul>").append(System.lineSeparator());
137207
}
138208

139209
}

codegen/src/main/java/software/amazon/awssdk/codegen/internal/Constant.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ public final class Constant {
9898

9999
public static final String AWS_DOCS_HOST = "docs.aws.amazon.com";
100100

101+
public static final String EXAMPLE_META_PATH = "software/amazon/awssdk/codegen/example-meta.json";
102+
101103
public static final String APPROVED_SIMPLE_METHOD_VERBS = "(get|list|describe|lookup|batchGet).*";
102104

103105
public static final String ASYNC_STREAMING_INPUT_PARAM = "requestBody";

0 commit comments

Comments
 (0)