19
19
import java .io .File ;
20
20
import java .io .IOException ;
21
21
import java .io .PrintWriter ;
22
+ import java .util .ArrayList ;
23
+ import java .util .Collections ;
24
+ import java .util .List ;
22
25
import java .util .concurrent .ForkJoinTask ;
23
26
import software .amazon .awssdk .codegen .emitters .GeneratorTask ;
24
27
import software .amazon .awssdk .codegen .emitters .GeneratorTaskParams ;
25
28
import software .amazon .awssdk .codegen .emitters .tasks .AwsGeneratorTasks ;
26
29
import software .amazon .awssdk .codegen .internal .Jackson ;
27
30
import software .amazon .awssdk .codegen .internal .Utils ;
28
31
import software .amazon .awssdk .codegen .model .intermediate .IntermediateModel ;
32
+ import software .amazon .awssdk .codegen .validation .ModelValidationContext ;
33
+ import software .amazon .awssdk .codegen .validation .ModelValidationReport ;
34
+ import software .amazon .awssdk .codegen .validation .ModelValidator ;
35
+ import software .amazon .awssdk .codegen .validation .ValidationEntry ;
29
36
import software .amazon .awssdk .utils .Logger ;
30
37
31
38
public class CodeGenerator {
32
39
private static final Logger log = Logger .loggerFor (CodeGenerator .class );
33
40
private static final String MODEL_DIR_NAME = "models" ;
34
41
35
- private final C2jModels models ;
42
+ // TODO: add validators
43
+ private static final List <ModelValidator > DEFAULT_MODEL_VALIDATORS = Collections .emptyList ();
44
+
45
+ private final C2jModels c2jModels ;
46
+
47
+ private final IntermediateModel intermediateModel ;
48
+ private final IntermediateModel shareModelsTarget ;
36
49
private final String sourcesDirectory ;
37
50
private final String resourcesDirectory ;
38
51
private final String testsDirectory ;
@@ -42,6 +55,9 @@ public class CodeGenerator {
42
55
*/
43
56
private final String fileNamePrefix ;
44
57
58
+ private final List <ModelValidator > modelValidators ;
59
+ private final boolean emitValidationReport ;
60
+
45
61
static {
46
62
// Make sure ClassName is statically initialized before we do anything in parallel.
47
63
// Parallel static initialization of ClassName and TypeName can result in a deadlock:
@@ -50,12 +66,21 @@ public class CodeGenerator {
50
66
}
51
67
52
68
public CodeGenerator (Builder builder ) {
53
- this .models = builder .models ;
69
+ this .c2jModels = builder .models ;
70
+ this .intermediateModel = builder .intermediateModel ;
71
+
72
+ if (this .c2jModels != null && this .intermediateModel != null ) {
73
+ throw new IllegalArgumentException ("Only one of c2jModels and intermediateModel must be specified" );
74
+ }
75
+
76
+ this .shareModelsTarget = builder .shareModelsTarget ;
54
77
this .sourcesDirectory = builder .sourcesDirectory ;
55
78
this .testsDirectory = builder .testsDirectory ;
56
79
this .resourcesDirectory = builder .resourcesDirectory != null ? builder .resourcesDirectory
57
80
: builder .sourcesDirectory ;
58
81
this .fileNamePrefix = builder .fileNamePrefix ;
82
+ this .modelValidators = builder .modelValidators == null ? DEFAULT_MODEL_VALIDATORS : builder .modelValidators ;
83
+ this .emitValidationReport = builder .emitValidationReport ;
59
84
}
60
85
61
86
public static File getModelDirectory (String outputDirectory ) {
@@ -76,13 +101,31 @@ public static Builder builder() {
76
101
* code.
77
102
*/
78
103
public void execute () {
79
- try {
80
- IntermediateModel intermediateModel = new IntermediateModelBuilder (models ).build ();
104
+ ModelValidationReport report = new ModelValidationReport ();
105
+
106
+ IntermediateModel modelToGenerate ;
107
+ if (c2jModels != null ) {
108
+ modelToGenerate = new IntermediateModelBuilder (c2jModels ).build ();
109
+ } else {
110
+ modelToGenerate = intermediateModel ;
111
+ }
112
+
113
+ List <ValidationEntry > validatorEntries = runModelValidators (modelToGenerate );
114
+ report .setValidationEntries (validatorEntries );
81
115
116
+ if (emitValidationReport ) {
117
+ writeValidationReport (report );
118
+ }
119
+
120
+ if (!validatorEntries .isEmpty ()) {
121
+ throw new RuntimeException ("Validation failed. See validation report for details." );
122
+ }
123
+
124
+ try {
82
125
if (fileNamePrefix != null ) {
83
- writeIntermediateModel (intermediateModel );
126
+ writeIntermediateModel (modelToGenerate );
84
127
}
85
- emitCode (intermediateModel );
128
+ emitCode (modelToGenerate );
86
129
87
130
} catch (Exception e ) {
88
131
log .error (() -> "Failed to generate code. " , e );
@@ -91,7 +134,32 @@ public void execute() {
91
134
}
92
135
}
93
136
137
+ private List <ValidationEntry > runModelValidators (IntermediateModel intermediateModel ) {
138
+ ModelValidationContext ctx = ModelValidationContext .builder ()
139
+ .intermediateModel (intermediateModel )
140
+ .shareModelsTarget (shareModelsTarget )
141
+ .build ();
142
+
143
+ List <ValidationEntry > validationEntries = new ArrayList <>();
144
+
145
+ modelValidators .forEach (v -> validationEntries .addAll (v .validateModels (ctx )));
146
+
147
+ return validationEntries ;
148
+ }
149
+
150
+ private void writeValidationReport (ModelValidationReport report ) {
151
+ try {
152
+ writeModel (report , "validation-report.json" );
153
+ } catch (IOException e ) {
154
+ throw new RuntimeException (e );
155
+ }
156
+ }
157
+
94
158
private void writeIntermediateModel (IntermediateModel model ) throws IOException {
159
+ writeModel (model , fileNamePrefix + "-intermediate.json" );
160
+ }
161
+
162
+ private void writeModel (Object model , String name ) throws IOException {
95
163
File modelDir = getModelDirectory (sourcesDirectory );
96
164
PrintWriter writer = null ;
97
165
try {
@@ -100,7 +168,7 @@ private void writeIntermediateModel(IntermediateModel model) throws IOException
100
168
throw new RuntimeException ("Failed to create " + outDir .getAbsolutePath ());
101
169
}
102
170
103
- File outputFile = new File (modelDir , fileNamePrefix + "-intermediate.json" );
171
+ File outputFile = new File (modelDir , name );
104
172
105
173
if (!outputFile .exists () && !outputFile .createNewFile ()) {
106
174
throw new RuntimeException ("Error creating file " + outputFile .getAbsolutePath ());
@@ -134,10 +202,14 @@ private GeneratorTask createGeneratorTasks(IntermediateModel intermediateModel)
134
202
public static final class Builder {
135
203
136
204
private C2jModels models ;
205
+ private IntermediateModel intermediateModel ;
206
+ private IntermediateModel shareModelsTarget ;
137
207
private String sourcesDirectory ;
138
208
private String resourcesDirectory ;
139
209
private String testsDirectory ;
140
210
private String fileNamePrefix ;
211
+ private List <ModelValidator > modelValidators ;
212
+ private boolean emitValidationReport ;
141
213
142
214
private Builder () {
143
215
}
@@ -147,6 +219,16 @@ public Builder models(C2jModels models) {
147
219
return this ;
148
220
}
149
221
222
+ public Builder intermediateModel (IntermediateModel intermediateModel ) {
223
+ this .intermediateModel = intermediateModel ;
224
+ return this ;
225
+ }
226
+
227
+ public Builder shareModelsTarget (IntermediateModel shareModelsTarget ) {
228
+ this .shareModelsTarget = shareModelsTarget ;
229
+ return this ;
230
+ }
231
+
150
232
public Builder sourcesDirectory (String sourcesDirectory ) {
151
233
this .sourcesDirectory = sourcesDirectory ;
152
234
return this ;
@@ -167,6 +249,16 @@ public Builder intermediateModelFileNamePrefix(String fileNamePrefix) {
167
249
return this ;
168
250
}
169
251
252
+ public Builder modelValidators (List <ModelValidator > modelValidators ) {
253
+ this .modelValidators = modelValidators ;
254
+ return this ;
255
+ }
256
+
257
+ public Builder emitValidationReport (boolean emitValidationReport ) {
258
+ this .emitValidationReport = emitValidationReport ;
259
+ return this ;
260
+ }
261
+
170
262
/**
171
263
* @return An immutable {@link CodeGenerator} object.
172
264
*/
0 commit comments