5
5
import io .swagger .codegen .CodegenConfig ;
6
6
import io .swagger .codegen .CodegenConstants ;
7
7
import io .swagger .codegen .CodegenType ;
8
+ import io .swagger .codegen .CodegenModel ;
8
9
import io .swagger .codegen .DefaultCodegen ;
9
10
import io .swagger .codegen .SupportingFile ;
10
11
import io .swagger .codegen .CodegenProperty ;
11
12
import io .swagger .codegen .CodegenModel ;
12
13
import io .swagger .codegen .CodegenOperation ;
13
14
import io .swagger .models .properties .*;
14
15
import io .swagger .codegen .CliOption ;
16
+ import io .swagger .models .Model ;
15
17
16
18
import java .io .File ;
17
19
import java .util .Arrays ;
18
20
import java .util .HashMap ;
19
21
import java .util .HashSet ;
20
22
import java .util .List ;
21
23
import java .util .Map ;
24
+ import java .util .ArrayList ;
25
+ import java .util .Iterator ;
22
26
23
27
import org .apache .commons .lang .StringUtils ;
28
+ import org .apache .commons .lang .WordUtils ;
24
29
import org .slf4j .Logger ;
25
30
import org .slf4j .LoggerFactory ;
26
31
@@ -37,6 +42,7 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen {
37
42
protected String packageCompany = "Swagger" ;
38
43
protected String packageCopyright = "No Copyright" ;
39
44
protected String clientPackage = "IO.Swagger.Client" ;
45
+ protected String localVariablePrefix = "" ;
40
46
41
47
protected String targetFramework = NET45 ;
42
48
protected String targetFrameworkNuget = "net45" ;
@@ -115,6 +121,10 @@ public CSharpClientCodegen() {
115
121
addSwitch (CodegenConstants .OPTIONAL_PROJECT_FILE ,
116
122
CodegenConstants .OPTIONAL_PROJECT_FILE_DESC ,
117
123
this .optionalProjectFileFlag );
124
+
125
+ addSwitch (CodegenConstants .OPTIONAL_EMIT_DEFAULT_VALUES ,
126
+ CodegenConstants .OPTIONAL_EMIT_DEFAULT_VALUES_DESC ,
127
+ this .optionalEmitDefaultValue );
118
128
}
119
129
120
130
@ Override
@@ -133,6 +143,7 @@ public void processOpts() {
133
143
additionalProperties .put ("packageDescription" , packageDescription );
134
144
additionalProperties .put ("packageCompany" , packageCompany );
135
145
additionalProperties .put ("packageCopyright" , packageCopyright );
146
+ additionalProperties .put ("emitDefaultValue" , optionalEmitDefaultValue );
136
147
137
148
if (additionalProperties .containsKey (CodegenConstants .DOTNET_FRAMEWORK )) {
138
149
setTargetFramework ((String ) additionalProperties .get (CodegenConstants .DOTNET_FRAMEWORK ));
@@ -253,6 +264,18 @@ public void setOptionalAssemblyInfoFlag(boolean flag) {
253
264
this .optionalAssemblyInfoFlag = flag ;
254
265
}
255
266
267
+ @ Override
268
+ public CodegenModel fromModel (String name , Model model , Map <String , Model > allDefinitions ) {
269
+ CodegenModel codegenModel = super .fromModel (name , model , allDefinitions );
270
+ if (allDefinitions != null && codegenModel != null && codegenModel .parent != null && codegenModel .hasEnums ) {
271
+ final Model parentModel = allDefinitions .get (toModelName (codegenModel .parent ));
272
+ final CodegenModel parentCodegenModel = super .fromModel (codegenModel .parent , parentModel );
273
+ codegenModel = this .reconcileInlineEnums (codegenModel , parentCodegenModel );
274
+ }
275
+
276
+ return codegenModel ;
277
+ }
278
+
256
279
public void setOptionalProjectFileFlag (boolean flag ) {
257
280
this .optionalProjectFileFlag = flag ;
258
281
}
@@ -261,6 +284,73 @@ public void setPackageGuid(String packageGuid) {
261
284
this .packageGuid = packageGuid ;
262
285
}
263
286
287
+ @ Override
288
+ public Map <String , Object > postProcessModels (Map <String , Object > objs ) {
289
+ List <Object > models = (List <Object >) objs .get ("models" );
290
+ for (Object _mo : models ) {
291
+ Map <String , Object > mo = (Map <String , Object >) _mo ;
292
+ CodegenModel cm = (CodegenModel ) mo .get ("model" );
293
+ for (CodegenProperty var : cm .vars ) {
294
+ Map <String , Object > allowableValues = var .allowableValues ;
295
+
296
+ // handle ArrayProperty
297
+ if (var .items != null ) {
298
+ allowableValues = var .items .allowableValues ;
299
+ }
300
+
301
+ if (allowableValues == null ) {
302
+ continue ;
303
+ }
304
+ List <String > values = (List <String >) allowableValues .get ("values" );
305
+ if (values == null ) {
306
+ continue ;
307
+ }
308
+
309
+ // put "enumVars" map into `allowableValues", including `name` and `value`
310
+ List <Map <String , String >> enumVars = new ArrayList <Map <String , String >>();
311
+ String commonPrefix = findCommonPrefixOfVars (values );
312
+ int truncateIdx = commonPrefix .length ();
313
+ for (String value : values ) {
314
+ Map <String , String > enumVar = new HashMap <String , String >();
315
+ String enumName ;
316
+ if (truncateIdx == 0 ) {
317
+ enumName = value ;
318
+ } else {
319
+ enumName = value .substring (truncateIdx );
320
+ if ("" .equals (enumName )) {
321
+ enumName = value ;
322
+ }
323
+ }
324
+ enumVar .put ("name" , toEnumVarName (enumName ));
325
+ enumVar .put ("jsonname" , value );
326
+ enumVar .put ("value" , value );
327
+ enumVars .add (enumVar );
328
+ }
329
+ allowableValues .put ("enumVars" , enumVars );
330
+ // handle default value for enum, e.g. available => StatusEnum.AVAILABLE
331
+ if (var .defaultValue != null ) {
332
+ String enumName = null ;
333
+ for (Map <String , String > enumVar : enumVars ) {
334
+ if (var .defaultValue .equals (enumVar .get ("value" ))) {
335
+ enumName = enumVar .get ("name" );
336
+ break ;
337
+ }
338
+ }
339
+ if (enumName != null ) {
340
+ var .defaultValue = var .datatypeWithEnum + "." + enumName ;
341
+ }
342
+ }
343
+
344
+ // HACK: strip ? from enum
345
+ if (var .datatypeWithEnum != null ) {
346
+ var .vendorExtensions .put ("plainDatatypeWithEnum" , var .datatypeWithEnum .substring (0 , var .datatypeWithEnum .length () - 1 ));
347
+ }
348
+ }
349
+ }
350
+
351
+ return objs ;
352
+ }
353
+
264
354
public void setTargetFramework (String dotnetFramework ) {
265
355
if (!frameworks .containsKey (dotnetFramework )){
266
356
LOGGER .warn ("Invalid .NET framework version, defaulting to " + this .targetFramework );
@@ -270,6 +360,82 @@ public void setTargetFramework(String dotnetFramework) {
270
360
LOGGER .info ("Generating code for .NET Framework " + this .targetFramework );
271
361
}
272
362
363
+ private CodegenModel reconcileInlineEnums (CodegenModel codegenModel , CodegenModel parentCodegenModel ) {
364
+ // This generator uses inline classes to define enums, which breaks when
365
+ // dealing with models that have subTypes. To clean this up, we will analyze
366
+ // the parent and child models, look for enums that match, and remove
367
+ // them from the child models and leave them in the parent.
368
+ // Because the child models extend the parents, the enums will be available via the parent.
369
+
370
+ // Only bother with reconciliation if the parent model has enums.
371
+ if (parentCodegenModel .hasEnums ) {
372
+
373
+ // Get the properties for the parent and child models
374
+ final List <CodegenProperty > parentModelCodegenProperties = parentCodegenModel .vars ;
375
+ List <CodegenProperty > codegenProperties = codegenModel .vars ;
376
+
377
+ // Iterate over all of the parent model properties
378
+ boolean removedChildEnum = false ;
379
+ for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties ) {
380
+ // Look for enums
381
+ if (parentModelCodegenPropery .isEnum ) {
382
+ // Now that we have found an enum in the parent class,
383
+ // and search the child class for the same enum.
384
+ Iterator <CodegenProperty > iterator = codegenProperties .iterator ();
385
+ while (iterator .hasNext ()) {
386
+ CodegenProperty codegenProperty = iterator .next ();
387
+ if (codegenProperty .isEnum && codegenProperty .equals (parentModelCodegenPropery )) {
388
+ // We found an enum in the child class that is
389
+ // a duplicate of the one in the parent, so remove it.
390
+ iterator .remove ();
391
+ removedChildEnum = true ;
392
+ }
393
+ }
394
+ }
395
+ }
396
+
397
+ if (removedChildEnum ) {
398
+ // If we removed an entry from this model's vars, we need to ensure hasMore is updated
399
+ int count = 0 , numVars = codegenProperties .size ();
400
+ for (CodegenProperty codegenProperty : codegenProperties ) {
401
+ count += 1 ;
402
+ codegenProperty .hasMore = (count < numVars ) ? true : null ;
403
+ }
404
+ codegenModel .vars = codegenProperties ;
405
+ }
406
+ }
407
+
408
+ return codegenModel ;
409
+ }
410
+
411
+ private String findCommonPrefixOfVars (List <String > vars ) {
412
+ String prefix = StringUtils .getCommonPrefix (vars .toArray (new String [vars .size ()]));
413
+ // exclude trailing characters that should be part of a valid variable
414
+ // e.g. ["status-on", "status-off"] => "status-" (not "status-o")
415
+ return prefix .replaceAll ("[a-zA-Z0-9]+\\ z" , "" );
416
+ }
417
+
418
+ private String toEnumVarName (String value ) {
419
+ String var = value .replaceAll ("_" , " " );
420
+ var = WordUtils .capitalizeFully (var );
421
+ var = var .replaceAll ("\\ W+" , "" );
422
+
423
+ if (var .matches ("\\ d.*" )) {
424
+ return "_" + var ;
425
+ } else {
426
+ return var ;
427
+ }
428
+ }
429
+
430
+
431
+ public void setPackageName (String packageName ) {
432
+ this .packageName = packageName ;
433
+ }
434
+
435
+ public void setPackageVersion (String packageVersion ) {
436
+ this .packageVersion = packageVersion ;
437
+ }
438
+
273
439
public void setTargetFrameworkNuget (String targetFrameworkNuget ) {
274
440
this .targetFrameworkNuget = targetFrameworkNuget ;
275
441
}
0 commit comments