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 ;
23+ import java .util .Map ;
24+ import java .util .stream .Collectors ;
2025import software .amazon .awssdk .codegen .emitters .GeneratorTask ;
2126import software .amazon .awssdk .codegen .emitters .GeneratorTaskParams ;
2227import software .amazon .awssdk .codegen .emitters .SimpleGeneratorTask ;
28+ import software .amazon .awssdk .codegen .internal .ExampleMetadataProvider ;
2329import software .amazon .awssdk .codegen .model .intermediate .Metadata ;
30+ import software .amazon .awssdk .utils .CollectionUtils ;
2431
2532/**
2633 * Emits the package-info.java for the base service package. Includes the service
27- * level documentation.
34+ * level documentation and code examples for that service organized by category .
2835 */
2936public final class PackageInfoGeneratorTasks extends BaseGeneratorTasks {
3037
38+ /**
39+ * Mapping from internal category names to user-friendly display names.
40+ * This defines the preferred order and display format for code example categories.
41+ */
42+ private static final Map <String , String > CATEGORY_DISPLAY_MAPPING ;
43+
44+ static {
45+ Map <String , String > mapping = new LinkedHashMap <>();
46+ mapping .put ("Hello" , "Getting Started" );
47+ mapping .put ("Basics" , "Basics" );
48+ mapping .put ("Api" , "API Actions" );
49+ mapping .put ("Scenarios" , "Scenarios" );
50+ mapping .put ("Serverless examples" , "Serverless Examples" );
51+ CATEGORY_DISPLAY_MAPPING = Collections .unmodifiableMap (mapping );
52+ }
53+
3154 private final String baseDirectory ;
3255
3356 PackageInfoGeneratorTasks (GeneratorTaskParams dependencies ) {
@@ -38,17 +61,150 @@ public final class PackageInfoGeneratorTasks extends BaseGeneratorTasks {
3861 @ Override
3962 protected List <GeneratorTask > createTasks () throws Exception {
4063 Metadata metadata = model .getMetadata ();
41- String packageInfoContents =
42- String .format ("/**%n"
43- + " * %s%n"
44- + "*/%n"
45- + "package %s;" ,
46- metadata .getDocumentation (),
47- metadata .getFullClientPackageName ());
64+ String packageInfoContents = buildPackageInfoContent (metadata , EXAMPLE_META_PATH );
65+
4866 return Collections .singletonList (new SimpleGeneratorTask (baseDirectory ,
4967 "package-info.java" ,
5068 model .getFileHeader (),
5169 () -> packageInfoContents ));
5270 }
5371
72+ /**
73+ * Builds the complete package-info.java content including Javadoc and package declaration.
74+ *
75+ * @param metadata the service metadata containing documentation and package information
76+ * @param exampleMetaPath the path to the example metadata JSON file
77+ * @return the complete package-info.java file content
78+ */
79+ String buildPackageInfoContent (Metadata metadata , String exampleMetaPath ) {
80+ String baseDocumentation = metadata .getDocumentation ();
81+ String codeExamples = getCodeExamplesWithPath (metadata , exampleMetaPath );
82+ String javadocContent = buildJavadocContent (baseDocumentation , codeExamples );
83+
84+ return javadocContent + System .lineSeparator () + "package " + metadata .getFullClientPackageName () + ";" ;
85+ }
86+
87+ /**
88+ * Builds the Javadoc comment content for the package-info.java file.
89+ *
90+ * @param baseDocumentation the base service documentation
91+ * @param codeExamples the formatted code examples content, or empty string if none
92+ * @return the complete Javadoc comment including opening and closing markers
93+ */
94+ private String buildJavadocContent (String baseDocumentation , String codeExamples ) {
95+ StringBuilder javadoc = new StringBuilder ();
96+ javadoc .append ("/**" ).append (System .lineSeparator ());
97+ javadoc .append (" * " ).append (baseDocumentation ).append (System .lineSeparator ());
98+
99+ if (!codeExamples .isEmpty ()) {
100+ javadoc .append (" *" ).append (System .lineSeparator ());
101+ javadoc .append (" * " ).append (codeExamples ).append (System .lineSeparator ());
102+ }
103+
104+ javadoc .append (" */" );
105+ return javadoc .toString ();
106+ }
107+
108+ /**
109+ * Gets code examples using a custom example metadata path.
110+ */
111+ private String getCodeExamplesWithPath (Metadata metadata , String exampleMetaPath ) {
112+ ExampleMetadataProvider exampleProvider = new ExampleMetadataProvider (exampleMetaPath );
113+ List <ExampleMetadataProvider .ExampleData > examples = exampleProvider .getServiceCodeExamples (metadata );
114+
115+ if (examples .isEmpty ()) {
116+ return "" ;
117+ }
118+
119+ return generateCodeExamplesJavadoc (examples );
120+ }
121+
122+ private String generateCodeExamplesJavadoc (List <ExampleMetadataProvider .ExampleData > examples ) {
123+ Map <String , List <ExampleMetadataProvider .ExampleData >> categorizedExamples =
124+ examples .stream ().collect (Collectors .groupingBy (ExampleMetadataProvider .ExampleData ::getCategory ,
125+ LinkedHashMap ::new ,
126+ Collectors .toList ()));
127+
128+ StringBuilder javadoc = new StringBuilder ();
129+ javadoc .append ("<h2>Code Examples</h2>" ).append (System .lineSeparator ());
130+ javadoc .append ("<p>For code examples demonstrating how to use this service with the AWS SDK for Java v2, see:</p>" )
131+ .append (System .lineSeparator ());
132+
133+ appendPredefinedCategories (javadoc , categorizedExamples , CATEGORY_DISPLAY_MAPPING );
134+ appendRemainingCategories (javadoc , categorizedExamples , CATEGORY_DISPLAY_MAPPING );
135+
136+ return formatAsJavadocLines (javadoc .toString ());
137+ }
138+
139+ /**
140+ * Formats HTML content as properly indented Javadoc comment lines.
141+ * Each non-empty line gets prefixed with appropriate Javadoc comment formatting.
142+ *
143+ * @param htmlContent the HTML content to format for Javadoc
144+ * @return formatted string ready for inclusion in Javadoc comments
145+ */
146+ private String formatAsJavadocLines (String htmlContent ) {
147+ StringBuilder result = new StringBuilder ();
148+ String [] lines = htmlContent .split (System .lineSeparator ());
149+
150+ for (int i = 0 ; i < lines .length ; i ++) {
151+ String line = lines [i ];
152+ if (!line .trim ().isEmpty ()) {
153+ result .append (line );
154+ if (i < lines .length - 1 ) {
155+ result .append (System .lineSeparator ()).append (" * " );
156+ }
157+ }
158+ }
159+ return result .toString ();
160+ }
161+
162+ /**
163+ * Appends predefined categories to the Javadoc in the preferred order.
164+ * Only includes categories that exist in the categorized examples and have content.
165+ */
166+ private void appendPredefinedCategories (StringBuilder javadoc ,
167+ Map <String , List <ExampleMetadataProvider .ExampleData >> categorizedExamples ,
168+ Map <String , String > categoryMapping ) {
169+ categoryMapping .forEach ((category , displayName ) ->
170+ appendCategoryIfExists (javadoc , categorizedExamples , category , displayName ));
171+ }
172+
173+ /**
174+ * Appends any remaining categories that weren't in the predefined mapping.
175+ */
176+ private void appendRemainingCategories (StringBuilder javadoc ,
177+ Map <String , List <ExampleMetadataProvider .ExampleData >> categorizedExamples ,
178+ Map <String , String > categoryMapping ) {
179+ categorizedExamples .entrySet ().stream ()
180+ .filter (entry -> !categoryMapping .containsKey (entry .getKey ()))
181+ .forEach (entry -> appendCategoryIfExists (javadoc , categorizedExamples , entry .getKey (),
182+ entry .getKey ()));
183+ }
184+
185+ /**
186+ * Appends a category section if examples exist for the given category.
187+ */
188+ private void appendCategoryIfExists (StringBuilder javadoc ,
189+ Map <String , List <ExampleMetadataProvider .ExampleData >> categorizedExamples ,
190+ String category ,
191+ String displayName ) {
192+ List <ExampleMetadataProvider .ExampleData > categoryExamples = categorizedExamples .get (category );
193+ if (!CollectionUtils .isNullOrEmpty (categoryExamples )) {
194+ appendCategorySection (javadoc , displayName , categoryExamples );
195+ }
196+ }
197+
198+ private void appendCategorySection (StringBuilder javadoc , String displayName ,
199+ List <ExampleMetadataProvider .ExampleData > categoryExamples ) {
200+ javadoc .append ("<h3>" ).append (displayName ).append ("</h3>" ).append (System .lineSeparator ());
201+ javadoc .append ("<ul>" ).append (System .lineSeparator ());
202+
203+ for (ExampleMetadataProvider .ExampleData example : categoryExamples ) {
204+ javadoc .append ("<li><a href=\" " ).append (example .getUrl ()).append ("\" target=\" _top\" >" )
205+ .append (example .getTitle ()).append ("</a></li>" ).append (System .lineSeparator ());
206+ }
207+ javadoc .append ("</ul>" ).append (System .lineSeparator ());
208+ }
209+
54210}
0 commit comments