Repository: cjbooms/fabrikt
Pull request #98 (2021-12-16 16:07:35)

Only make it a data class if there are constructor parameters. 
There are cases as in the added example where it's desirable to have a polymorphic subtype that is just a marker class containing a hard-coded discriminator value


Patch:
diff --git a/src/main/kotlin/com/cjbooms/fabrikt/generators/model/JacksonModelGenerator.kt b/src/main/kotlin/com/cjbooms/fabrikt/generators/model/JacksonModelGenerator.kt
index 55bb7af..53a65c4 100644
--- a/src/main/kotlin/com/cjbooms/fabrikt/generators/model/JacksonModelGenerator.kt
+++ b/src/main/kotlin/com/cjbooms/fabrikt/generators/model/JacksonModelGenerator.kt
@@ -331,21 +331,14 @@ class JacksonModelGenerator(
             )
         } else null
 
-    private fun standardDataClass(modelName: String, properties: Collection<PropertyInfo>): TypeSpec =
-        properties.addToClass(
-            TypeSpec
-                .classBuilder(
-                    generatedType(
-                        packages.base,
-                        modelName
-                    )
-                )
-                .addModifiers(KModifier.DATA)
-                .addSerializableInterface()
-                .addQuarkusReflectionAnnotation()
-                .addMicronautIntrospectedAnnotation(),
-            ClassType.VANILLA_MODEL
-        )
+    private fun standardDataClass(modelName: String, properties: Collection<PropertyInfo>): TypeSpec {
+        val classBuilder = TypeSpec.classBuilder(generatedType(packages.base, modelName))
+            .addSerializableInterface()
+            .addQuarkusReflectionAnnotation()
+            .addMicronautIntrospectedAnnotation()
+        properties.addToClass(classBuilder, ClassType.VANILLA_MODEL)
+        return classBuilder.build()
+    }
 
     private fun polymorphicSuperType(
         modelName: String,
@@ -353,14 +346,9 @@ class JacksonModelGenerator(
         discriminator: Discriminator,
         allSchemas: List<SchemaInfo>
     ): TypeSpec {
-        val classBuilder = TypeSpec.classBuilder(
-            generatedType(
-                packages.base,
-                modelName
-            )
-        )
+        val classBuilder = TypeSpec.classBuilder(generatedType(packages.base, modelName))
             .addModifiers(KModifier.SEALED)
-        classBuilder.addAnnotation(basePolymorphicType(discriminator.propertyName))
+            .addAnnotation(basePolymorphicType(discriminator.propertyName))
 
         val subTypes = allSchemas
             .filter { model ->
@@ -380,39 +368,34 @@ class JacksonModelGenerator(
             .addQuarkusReflectionAnnotation()
             .addMicronautIntrospectedAnnotation()
 
-        return properties.addToClass(
-            classBuilder,
-            ClassType.SUPER_MODEL
-        )
+        properties.addToClass(classBuilder, ClassType.SUPER_MODEL)
+
+        return classBuilder.build()
     }
 
     private fun polymorphicSubType(
         modelName: String,
         properties: Collection<PropertyInfo>,
         superType: SchemaInfo
-    ): TypeSpec =
+    ): TypeSpec {
+        val classBuilder = TypeSpec.classBuilder(generatedType(packages.base, modelName))
+            .addSerializableInterface()
+            .addQuarkusReflectionAnnotation()
+            .addMicronautIntrospectedAnnotation()
+            .superclass(
+                toModelType(packages.base, KotlinTypeInfo.from(superType.schema, superType.name))
+            )
         properties.addToClass(
-            TypeSpec
-                .classBuilder(
-                    generatedType(
-                        packages.base,
-                        modelName
-                    )
-                )
-                .addModifiers(KModifier.DATA)
-                .addSerializableInterface()
-                .addQuarkusReflectionAnnotation()
-                .addMicronautIntrospectedAnnotation()
-                .superclass(
-                    toModelType(
-                        packages.base,
-                        KotlinTypeInfo.from(superType.schema, superType.name)
-                    )
-                ),
+            classBuilder,
             ClassType.SUB_MODEL
         )
+        return classBuilder.build()
+    }
 
-    private fun Collection<PropertyInfo>.addToClass(classBuilder: TypeSpec.Builder, classType: ClassType): TypeSpec {
+    private fun Collection<PropertyInfo>.addToClass(
+        classBuilder: TypeSpec.Builder,
+        classType: ClassType
+    ): TypeSpec.Builder {
         val constructorBuilder = FunSpec.constructorBuilder()
         this.forEach {
             it.addToClass(
@@ -430,7 +413,8 @@ class JacksonModelGenerator(
                 classType
             )
         }
-        return classBuilder.primaryConstructor(constructorBuilder.build()).build()
+        if (constructorBuilder.parameters.isNotEmpty() && classBuilder.modifiers.isEmpty()) classBuilder.addModifiers(KModifier.DATA)
+        return classBuilder.primaryConstructor(constructorBuilder.build())
     }
 
     private fun TypeSpec.Builder.addSerializableInterface(): TypeSpec.Builder {


Test patch:
diff --git a/src/test/resources/examples/enumPolymorphicDiscriminator/api.yaml b/src/test/resources/examples/enumPolymorphicDiscriminator/api.yaml
index 783fec1..b0f17ac 100644
--- a/src/test/resources/examples/enumPolymorphicDiscriminator/api.yaml
+++ b/src/test/resources/examples/enumPolymorphicDiscriminator/api.yaml
@@ -13,6 +13,7 @@ components:
           obj_one_only: '#/components/schemas/ConcreteImplOne'
           obj_two_first: '#/components/schemas/ConcreteImplTwo'
           obj_two_second: '#/components/schemas/ConcreteImplTwo'
+          obj_three: '#/components/schemas/ConcreteImplThree'
       properties:
         some_enum:
           $ref: '#/components/schemas/EnumDiscriminator'
@@ -32,6 +33,10 @@ components:
           properties:
             some_prop:
               type: string
+              
+    ConcreteImplThree:
+      allOf:
+        - $ref: '#/components/schemas/PolymorphicEnumDiscriminator'
 
     EnumDiscriminator:
       type: string
@@ -39,6 +44,7 @@ components:
         - obj_one_only
         - obj_two_first
         - obj_two_second
+        - obj_three
 
 
 
diff --git a/src/test/resources/examples/enumPolymorphicDiscriminator/models/Models.kt b/src/test/resources/examples/enumPolymorphicDiscriminator/models/Models.kt
index 820c176..9e3d77a 100644
--- a/src/test/resources/examples/enumPolymorphicDiscriminator/models/Models.kt
+++ b/src/test/resources/examples/enumPolymorphicDiscriminator/models/Models.kt
@@ -25,7 +25,12 @@ import kotlin.collections.Map
         name =
         "obj_two_first"
     ),
-    JsonSubTypes.Type(value = ConcreteImplTwo::class, name = "obj_two_second")
+    JsonSubTypes.Type(
+        value = ConcreteImplTwo::class,
+        name =
+        "obj_two_second"
+    ),
+    JsonSubTypes.Type(value = ConcreteImplThree::class, name = "obj_three")
 )
 sealed class PolymorphicEnumDiscriminator() {
     abstract val someEnum: EnumDiscriminator
@@ -39,7 +44,9 @@ enum class EnumDiscriminator(
 
     OBJ_TWO_FIRST("obj_two_first"),
 
-    OBJ_TWO_SECOND("obj_two_second");
+    OBJ_TWO_SECOND("obj_two_second"),
+
+    OBJ_THREE("obj_three");
 
     companion object {
         private val mapping: Map<String, EnumDiscriminator> =
@@ -68,3 +75,9 @@ data class ConcreteImplTwo(
     @get:JsonProperty("some_prop")
     val someProp: String? = null
 ) : PolymorphicEnumDiscriminator()
+
+class ConcreteImplThree() : PolymorphicEnumDiscriminator() {
+    @get:JsonProperty("some_enum")
+    @get:NotNull
+    override val someEnum: EnumDiscriminator = EnumDiscriminator.OBJ_THREE
+}