2121import java .nio .file .Path ;
2222import java .nio .file .Paths ;
2323import java .nio .file .attribute .BasicFileAttributes ;
24+ import java .util .HashMap ;
25+ import java .util .List ;
26+ import java .util .Map ;
2427import java .util .Optional ;
28+ import java .util .stream .Collectors ;
2529import java .util .stream .Stream ;
2630import org .apache .maven .plugin .AbstractMojo ;
2731import org .apache .maven .plugin .MojoExecutionException ;
3034import org .apache .maven .project .MavenProject ;
3135import software .amazon .awssdk .codegen .C2jModels ;
3236import software .amazon .awssdk .codegen .CodeGenerator ;
37+ import software .amazon .awssdk .codegen .IntermediateModelBuilder ;
3338import software .amazon .awssdk .codegen .internal .Utils ;
3439import software .amazon .awssdk .codegen .model .config .customization .CustomizationConfig ;
40+ import software .amazon .awssdk .codegen .model .intermediate .IntermediateModel ;
3541import software .amazon .awssdk .codegen .model .rules .endpoints .EndpointTestSuiteModel ;
3642import software .amazon .awssdk .codegen .model .service .EndpointRuleSetModel ;
3743import software .amazon .awssdk .codegen .model .service .Paginators ;
3844import software .amazon .awssdk .codegen .model .service .ServiceModel ;
3945import software .amazon .awssdk .codegen .model .service .Waiters ;
4046import software .amazon .awssdk .codegen .utils .ModelLoaderUtils ;
47+ import software .amazon .awssdk .utils .StringUtils ;
4148
4249/**
4350 * The Maven mojo to generate Java client code using software.amazon.awssdk:codegen module.
4451 */
4552@ Mojo (name = "generate" )
4653public class GenerationMojo extends AbstractMojo {
47-
4854 private static final String MODEL_FILE = "service-2.json" ;
4955 private static final String CUSTOMIZATION_CONFIG_FILE = "customization.config" ;
5056 private static final String WAITERS_FILE = "waiters-2.json" ;
@@ -62,6 +68,8 @@ public class GenerationMojo extends AbstractMojo {
6268 @ Parameter (property = "writeIntermediateModel" , defaultValue = "false" )
6369 private boolean writeIntermediateModel ;
6470
71+ @ Parameter (property = "writeValidationReport" , defaultValue = "false" )
72+ private boolean writeValidationReport ;
6573
6674 @ Parameter (defaultValue = "${project}" , readonly = true )
6775 private MavenProject project ;
@@ -76,22 +84,59 @@ public void execute() throws MojoExecutionException {
7684 this .resourcesDirectory = Paths .get (outputDirectory ).resolve ("generated-resources" ).resolve ("sdk-resources" );
7785 this .testsDirectory = Paths .get (outputDirectory ).resolve ("generated-test-sources" ).resolve ("sdk-tests" );
7886
79- findModelRoots ().forEach (p -> {
80- Path modelRootPath = p .modelRoot ;
81- getLog ().info ("Loading from: " + modelRootPath .toString ());
82- generateCode (C2jModels .builder ()
83- .customizationConfig (p .customizationConfig )
84- .serviceModel (loadServiceModel (modelRootPath ))
85- .waitersModel (loadWaiterModel (modelRootPath ))
86- .paginatorsModel (loadPaginatorModel (modelRootPath ))
87- .endpointRuleSetModel (loadEndpointRuleSetModel (modelRootPath ))
88- .endpointTestSuiteModel (loadEndpointTestSuiteModel (modelRootPath ))
89- .build ());
87+ List <GenerationParams > generationParams = initGenerationParams ();
88+
89+ Map <String , IntermediateModel > serviceNameToModelMap = new HashMap <>();
90+
91+ generationParams .forEach (
92+ params -> {
93+ IntermediateModel model = params .intermediateModel ;
94+ String lowercaseServiceName = StringUtils .lowerCase (model .getMetadata ().getServiceName ());
95+ IntermediateModel previous = serviceNameToModelMap .put (lowercaseServiceName , model );
96+ if (previous != null ) {
97+ String warning = String .format ("Multiple service models found with service name %s. Model validation "
98+ + "will likely be incorrect" , lowercaseServiceName );
99+ getLog ().warn (warning );
100+ }
101+ });
102+
103+ // Update each param with the intermediate model it shares models with, if any
104+ generationParams .forEach (params -> {
105+ CustomizationConfig customizationConfig = params .intermediateModel .getCustomizationConfig ();
106+
107+ if (customizationConfig .getShareModelConfig () != null ) {
108+ String shareModelWithName = customizationConfig .getShareModelConfig ().getShareModelWith ();
109+ params .withShareModelsTarget (serviceNameToModelMap .get (shareModelWithName ));
110+ }
90111 });
112+
113+ generationParams .forEach (this ::generateCode );
114+
91115 project .addCompileSourceRoot (sourcesDirectory .toFile ().getAbsolutePath ());
92116 project .addTestCompileSourceRoot (testsDirectory .toFile ().getAbsolutePath ());
93117 }
94118
119+ private List <GenerationParams > initGenerationParams () throws MojoExecutionException {
120+ List <ModelRoot > modelRoots = findModelRoots ().collect (Collectors .toList ());
121+
122+ return modelRoots .stream ().map (r -> {
123+ Path modelRootPath = r .modelRoot ;
124+ getLog ().info ("Loading from: " + modelRootPath .toString ());
125+ C2jModels c2jModels = C2jModels .builder ()
126+ .customizationConfig (r .customizationConfig )
127+ .serviceModel (loadServiceModel (modelRootPath ))
128+ .waitersModel (loadWaiterModel (modelRootPath ))
129+ .paginatorsModel (loadPaginatorModel (modelRootPath ))
130+ .endpointRuleSetModel (loadEndpointRuleSetModel (modelRootPath ))
131+ .endpointTestSuiteModel (loadEndpointTestSuiteModel (modelRootPath ))
132+ .build ();
133+ String intermediateModelFileNamePrefix = intermediateModelFileNamePrefix (c2jModels );
134+ IntermediateModel intermediateModel = new IntermediateModelBuilder (c2jModels ).build ();
135+ return new GenerationParams ().withIntermediateModel (intermediateModel )
136+ .withIntermediateModelFileNamePrefix (intermediateModelFileNamePrefix );
137+ }).collect (Collectors .toList ());
138+ }
139+
95140 private Stream <ModelRoot > findModelRoots () throws MojoExecutionException {
96141 try {
97142 return Files .find (codeGenResources .toPath (), 10 , this ::isModelFile )
@@ -111,13 +156,15 @@ private boolean isModelFile(Path p, BasicFileAttributes a) {
111156 return p .toString ().endsWith (MODEL_FILE );
112157 }
113158
114- private void generateCode (C2jModels models ) {
159+ private void generateCode (GenerationParams params ) {
115160 CodeGenerator .builder ()
116- .models (models )
161+ .intermediateModel (params .intermediateModel )
162+ .shareModelsTarget (params .shareModelsTarget )
117163 .sourcesDirectory (sourcesDirectory .toFile ().getAbsolutePath ())
118164 .resourcesDirectory (resourcesDirectory .toFile ().getAbsolutePath ())
119165 .testsDirectory (testsDirectory .toFile ().getAbsolutePath ())
120- .intermediateModelFileNamePrefix (intermediateModelFileNamePrefix (models ))
166+ .intermediateModelFileNamePrefix (params .intermediateModelFileNamePrefix )
167+ .emitValidationReport (writeValidationReport )
121168 .build ()
122169 .execute ();
123170 }
@@ -178,4 +225,25 @@ private ModelRoot(Path modelRoot, CustomizationConfig customizationConfig) {
178225 this .customizationConfig = customizationConfig ;
179226 }
180227 }
228+
229+ private static class GenerationParams {
230+ private IntermediateModel intermediateModel ;
231+ private IntermediateModel shareModelsTarget ;
232+ private String intermediateModelFileNamePrefix ;
233+
234+ public GenerationParams withIntermediateModel (IntermediateModel intermediateModel ) {
235+ this .intermediateModel = intermediateModel ;
236+ return this ;
237+ }
238+
239+ public GenerationParams withShareModelsTarget (IntermediateModel shareModelsTarget ) {
240+ this .shareModelsTarget = shareModelsTarget ;
241+ return this ;
242+ }
243+
244+ public GenerationParams withIntermediateModelFileNamePrefix (String intermediateModelFileNamePrefix ) {
245+ this .intermediateModelFileNamePrefix = intermediateModelFileNamePrefix ;
246+ return this ;
247+ }
248+ }
181249}
0 commit comments