1515
1616package software .amazon .awssdk .codegen .emitters .tasks ;
1717
18+ import static software .amazon .awssdk .codegen .internal .Constant .EXAMPLE_META_PATH ;
19+
1820import java .util .Collections ;
21+ import java .util .LinkedHashMap ;
1922import java .util .List ;
2023import java .util .Map ;
24+ import java .util .stream .Collectors ;
2125import software .amazon .awssdk .codegen .emitters .GeneratorTask ;
2226import software .amazon .awssdk .codegen .emitters .GeneratorTaskParams ;
2327import software .amazon .awssdk .codegen .emitters .SimpleGeneratorTask ;
24- import software .amazon .awssdk .codegen .internal .DocumentationUtils ;
28+ import software .amazon .awssdk .codegen .internal .ExampleMetadataProvider ;
2529import 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 */
3135public 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}
0 commit comments