21
21
import java .nio .file .Path ;
22
22
import java .nio .file .Paths ;
23
23
import java .nio .file .attribute .BasicFileAttributes ;
24
+ import java .util .HashMap ;
25
+ import java .util .List ;
26
+ import java .util .Map ;
24
27
import java .util .Optional ;
28
+ import java .util .stream .Collectors ;
25
29
import java .util .stream .Stream ;
26
30
import org .apache .maven .plugin .AbstractMojo ;
27
31
import org .apache .maven .plugin .MojoExecutionException ;
30
34
import org .apache .maven .project .MavenProject ;
31
35
import software .amazon .awssdk .codegen .C2jModels ;
32
36
import software .amazon .awssdk .codegen .CodeGenerator ;
37
+ import software .amazon .awssdk .codegen .IntermediateModelBuilder ;
33
38
import software .amazon .awssdk .codegen .internal .Utils ;
34
39
import software .amazon .awssdk .codegen .model .config .customization .CustomizationConfig ;
40
+ import software .amazon .awssdk .codegen .model .intermediate .IntermediateModel ;
35
41
import software .amazon .awssdk .codegen .model .rules .endpoints .EndpointTestSuiteModel ;
36
42
import software .amazon .awssdk .codegen .model .service .EndpointRuleSetModel ;
37
43
import software .amazon .awssdk .codegen .model .service .Paginators ;
38
44
import software .amazon .awssdk .codegen .model .service .ServiceModel ;
39
45
import software .amazon .awssdk .codegen .model .service .Waiters ;
40
46
import software .amazon .awssdk .codegen .utils .ModelLoaderUtils ;
47
+ import software .amazon .awssdk .utils .StringUtils ;
41
48
42
49
/**
43
50
* The Maven mojo to generate Java client code using software.amazon.awssdk:codegen module.
44
51
*/
45
52
@ Mojo (name = "generate" )
46
53
public class GenerationMojo extends AbstractMojo {
47
-
48
54
private static final String MODEL_FILE = "service-2.json" ;
49
55
private static final String CUSTOMIZATION_CONFIG_FILE = "customization.config" ;
50
56
private static final String WAITERS_FILE = "waiters-2.json" ;
@@ -62,6 +68,8 @@ public class GenerationMojo extends AbstractMojo {
62
68
@ Parameter (property = "writeIntermediateModel" , defaultValue = "false" )
63
69
private boolean writeIntermediateModel ;
64
70
71
+ @ Parameter (property = "writeValidationReport" , defaultValue = "false" )
72
+ private boolean writeValidationReport ;
65
73
66
74
@ Parameter (defaultValue = "${project}" , readonly = true )
67
75
private MavenProject project ;
@@ -76,22 +84,59 @@ public void execute() throws MojoExecutionException {
76
84
this .resourcesDirectory = Paths .get (outputDirectory ).resolve ("generated-resources" ).resolve ("sdk-resources" );
77
85
this .testsDirectory = Paths .get (outputDirectory ).resolve ("generated-test-sources" ).resolve ("sdk-tests" );
78
86
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
+ }
90
111
});
112
+
113
+ generationParams .forEach (this ::generateCode );
114
+
91
115
project .addCompileSourceRoot (sourcesDirectory .toFile ().getAbsolutePath ());
92
116
project .addTestCompileSourceRoot (testsDirectory .toFile ().getAbsolutePath ());
93
117
}
94
118
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
+
95
140
private Stream <ModelRoot > findModelRoots () throws MojoExecutionException {
96
141
try {
97
142
return Files .find (codeGenResources .toPath (), 10 , this ::isModelFile )
@@ -111,13 +156,15 @@ private boolean isModelFile(Path p, BasicFileAttributes a) {
111
156
return p .toString ().endsWith (MODEL_FILE );
112
157
}
113
158
114
- private void generateCode (C2jModels models ) {
159
+ private void generateCode (GenerationParams params ) {
115
160
CodeGenerator .builder ()
116
- .models (models )
161
+ .intermediateModel (params .intermediateModel )
162
+ .shareModelsTarget (params .shareModelsTarget )
117
163
.sourcesDirectory (sourcesDirectory .toFile ().getAbsolutePath ())
118
164
.resourcesDirectory (resourcesDirectory .toFile ().getAbsolutePath ())
119
165
.testsDirectory (testsDirectory .toFile ().getAbsolutePath ())
120
- .intermediateModelFileNamePrefix (intermediateModelFileNamePrefix (models ))
166
+ .intermediateModelFileNamePrefix (params .intermediateModelFileNamePrefix )
167
+ .emitValidationReport (writeValidationReport )
121
168
.build ()
122
169
.execute ();
123
170
}
@@ -178,4 +225,25 @@ private ModelRoot(Path modelRoot, CustomizationConfig customizationConfig) {
178
225
this .customizationConfig = customizationConfig ;
179
226
}
180
227
}
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
+ }
181
249
}
0 commit comments