@@ -236,8 +236,9 @@ public RustAxumServerCodegen() {
236
236
supportingFiles .add (new SupportingFile ("header.mustache" , "src" , "header.rs" ));
237
237
supportingFiles .add (new SupportingFile ("server-mod.mustache" , "src/server" , "mod.rs" ));
238
238
supportingFiles .add (new SupportingFile ("apis-mod.mustache" , apiPackage ().replace ('.' , File .separatorChar ), "mod.rs" ));
239
- supportingFiles .add (new SupportingFile ("README.mustache" , "" , "README.md" )
240
- .doNotOverwrite ());
239
+ // The file gets overwritten regardless
240
+ supportingFiles .add (new SupportingFile ("tests.mustache" , "src" , "tests.rs" ).doNotOverwrite ());
241
+ supportingFiles .add (new SupportingFile ("README.mustache" , "" , "README.md" ).doNotOverwrite ());
241
242
}
242
243
243
244
@ Override
@@ -594,8 +595,105 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation
594
595
return op ;
595
596
}
596
597
598
+ private void postProcessOneOfModels (List <ModelMap > allModels ) {
599
+ final HashMap <String , List <String >> oneOfMapDiscriminator = new HashMap <>();
600
+
601
+ for (ModelMap mo : allModels ) {
602
+ final CodegenModel cm = mo .getModel ();
603
+
604
+ final CodegenComposedSchemas cs = cm .getComposedSchemas ();
605
+ if (cs != null ) {
606
+ final List <CodegenProperty > csOneOf = cs .getOneOf ();
607
+
608
+ if (csOneOf != null ) {
609
+ for (CodegenProperty model : csOneOf ) {
610
+ // Generate a valid name for the enum variant.
611
+ // Mainly needed for primitive types.
612
+ String [] modelParts = model .dataType .replace ("<" , "Of" ).replace (">" , "" ).split ("::" );
613
+ model .datatypeWithEnum = camelize (modelParts [modelParts .length - 1 ]);
614
+
615
+ // Primitive type is not properly set, this overrides it to guarantee adequate model generation.
616
+ if (!model .getDataType ().matches (String .format (Locale .ROOT , ".*::%s" , model .getDatatypeWithEnum ()))) {
617
+ model .isPrimitiveType = true ;
618
+ }
619
+ }
620
+
621
+ cs .setOneOf (csOneOf );
622
+ cm .setComposedSchemas (cs );
623
+ }
624
+ }
625
+
626
+ if (cm .discriminator != null ) {
627
+ for (String model : cm .oneOf ) {
628
+ List <String > discriminators = oneOfMapDiscriminator .getOrDefault (model , new ArrayList <>());
629
+ discriminators .add (cm .discriminator .getPropertyName ());
630
+ oneOfMapDiscriminator .put (model , discriminators );
631
+ }
632
+ }
633
+ }
634
+
635
+ for (ModelMap mo : allModels ) {
636
+ final CodegenModel cm = mo .getModel ();
637
+
638
+ for (CodegenProperty var : cm .vars ) {
639
+ var .isDiscriminator = false ;
640
+ }
641
+
642
+ final List <String > discriminatorsForModel = oneOfMapDiscriminator .get (cm .getSchemaName ());
643
+
644
+ if (discriminatorsForModel != null ) {
645
+ for (String discriminator : discriminatorsForModel ) {
646
+ boolean hasDiscriminatorDefined = false ;
647
+
648
+ for (CodegenProperty var : cm .vars ) {
649
+ if (var .baseName .equals (discriminator )) {
650
+ var .isDiscriminator = true ;
651
+ hasDiscriminatorDefined = true ;
652
+ break ;
653
+ }
654
+ }
655
+
656
+ // If the discriminator field is not a defined attribute in the variant structure, create it.
657
+ if (!hasDiscriminatorDefined ) {
658
+ CodegenProperty property = new CodegenProperty ();
659
+
660
+ // Static attributes
661
+ // Only strings are supported by serde for tag field types, so it's the only one we'll deal with
662
+ property .openApiType = "string" ;
663
+ property .complexType = "string" ;
664
+ property .dataType = "String" ;
665
+ property .datatypeWithEnum = "String" ;
666
+ property .baseType = "string" ;
667
+ property .required = true ;
668
+ property .isPrimitiveType = true ;
669
+ property .isString = true ;
670
+ property .isDiscriminator = true ;
671
+
672
+ // Attributes based on the discriminator value
673
+ property .baseName = discriminator ;
674
+ property .name = discriminator ;
675
+ property .nameInCamelCase = camelize (discriminator );
676
+ property .nameInPascalCase = property .nameInCamelCase .substring (0 , 1 ).toUpperCase (Locale .ROOT ) + property .nameInCamelCase .substring (1 );
677
+ property .nameInSnakeCase = underscore (discriminator ).toUpperCase (Locale .ROOT );
678
+ property .getter = String .format (Locale .ROOT , "get%s" , property .nameInPascalCase );
679
+ property .setter = String .format (Locale .ROOT , "set%s" , property .nameInPascalCase );
680
+ property .defaultValueWithParam = String .format (Locale .ROOT , " = data.%s;" , property .name );
681
+
682
+ // Attributes based on the model name
683
+ property .defaultValue = String .format (Locale .ROOT , "r#\" %s\" #.to_string()" , cm .getSchemaName ());
684
+ property .jsonSchema = String .format (Locale .ROOT , "{ \" default\" :\" %s\" ; \" type\" :\" string\" }" , cm .getSchemaName ());
685
+
686
+ cm .vars .add (property );
687
+ }
688
+ }
689
+ }
690
+ }
691
+ }
692
+
597
693
@ Override
598
694
public OperationsMap postProcessOperationsWithModels (final OperationsMap operationsMap , List <ModelMap > allModels ) {
695
+ postProcessOneOfModels (allModels );
696
+
599
697
final OperationMap operations = operationsMap .getOperations ();
600
698
operations .put ("classnamePascalCase" , camelize (operations .getClassname ()));
601
699
0 commit comments