@@ -10,20 +10,25 @@ import io.swagger.v3.oas.annotations.media.{ArraySchema, Schema as SchemaAnnotat
10
10
import io .swagger .v3 .oas .models .media .Schema
11
11
12
12
import java .lang .annotation .Annotation
13
+ import java .lang .reflect .InvocationTargetException
13
14
import java .util .Iterator
14
15
import scala .reflect .Enum
16
+ import scala .util .Try
15
17
16
18
class SwaggerScala3EnumModelConverter extends ModelResolver (Json .mapper()) {
17
19
private val enumEntryClass = classOf [Enum ]
20
+ private val IntClass = classOf [Int ]
18
21
19
22
override def resolve (annotatedType : AnnotatedType , context : ModelConverterContext , chain : Iterator [ModelConverter ]): Schema [_] = {
20
23
val javaType = _mapper.constructType(annotatedType.getType)
21
24
val cls = javaType.getRawClass
22
25
if (isEnum(cls)) {
23
26
val sp : Schema [String ] = PrimitiveType .STRING .createProperty().asInstanceOf [Schema [String ]]
24
27
setRequired(annotatedType)
25
- getValues(cls).foreach { v =>
26
- sp.addEnumItemObject(v)
28
+ tryValues(cls).toOption.orElse(matchBasedOnOrdinals(cls)).map { values =>
29
+ values.foreach { v =>
30
+ sp.addEnumItemObject(v)
31
+ }
27
32
}
28
33
nullSafeList(annotatedType.getCtxAnnotations).foreach {
29
34
case p : Parameter => {
@@ -63,12 +68,48 @@ class SwaggerScala3EnumModelConverter extends ModelResolver(Json.mapper()) {
63
68
64
69
private def isEnum (cls : Class [_]): Boolean = enumEntryClass.isAssignableFrom(cls)
65
70
66
- private def getValues (cls : Class [_]): Seq [String ] = {
71
+ private def tryValues (cls : Class [_]): Try [ Seq [String ]] = Try {
67
72
val enumCompanion = Class .forName(cls.getName + " $" ).getField(" MODULE$" ).get(null )
68
73
val enumArray = enumCompanion.getClass.getDeclaredMethod(" values" ).invoke(enumCompanion).asInstanceOf [Array [Enum ]]
69
74
enumArray.sortBy(_.ordinal).map(_.toString).toSeq
70
75
}
71
76
77
+ private def matchBasedOnOrdinals (clz : Class [_]): Option [Seq [String ]] = {
78
+ val className = clz.getName
79
+ val companionObjectClassOption = if (className.endsWith(" $" )) {
80
+ Some (clz)
81
+ } else {
82
+ Try (Class .forName(className + " $" )).toOption
83
+ }
84
+ companionObjectClassOption.flatMap { companionObjectClass =>
85
+ Try (companionObjectClass.getField(" MODULE$" )).toOption.flatMap { moduleField =>
86
+ val instance = moduleField.get(None .orNull)
87
+ Try (clz.getMethod(" fromOrdinal" , IntClass )).toOption.map { method =>
88
+ var i = 0
89
+ var matched : Seq [String ] = Seq .empty[String ]
90
+ var complete = false
91
+ while (! complete) {
92
+ try {
93
+ val enumValue = method.invoke(instance, i)
94
+ matched = matched :+ enumValue.toString
95
+ } catch {
96
+ case _ : NoSuchElementException => complete = true
97
+ case itex : InvocationTargetException => {
98
+ Option (itex.getCause) match {
99
+ case Some (e) if e.isInstanceOf [NoSuchElementException ] => complete = true
100
+ case Some (e) => throw e
101
+ case _ => throw itex
102
+ }
103
+ }
104
+ }
105
+ i += 1
106
+ }
107
+ matched
108
+ }
109
+ }
110
+ }
111
+ }
112
+
72
113
private def setRequired (annotatedType : AnnotatedType ): Unit = annotatedType match {
73
114
case _ : AnnotatedTypeForOption => // not required
74
115
case _ => {
0 commit comments