@@ -10,20 +10,25 @@ import io.swagger.v3.oas.annotations.media.{ArraySchema, Schema as SchemaAnnotat
1010import io .swagger .v3 .oas .models .media .Schema
1111
1212import java .lang .annotation .Annotation
13+ import java .lang .reflect .InvocationTargetException
1314import java .util .Iterator
1415import scala .reflect .Enum
16+ import scala .util .Try
1517
1618class SwaggerScala3EnumModelConverter extends ModelResolver (Json .mapper()) {
1719 private val enumEntryClass = classOf [Enum ]
20+ private val IntClass = classOf [Int ]
1821
1922 override def resolve (annotatedType : AnnotatedType , context : ModelConverterContext , chain : Iterator [ModelConverter ]): Schema [_] = {
2023 val javaType = _mapper.constructType(annotatedType.getType)
2124 val cls = javaType.getRawClass
2225 if (isEnum(cls)) {
2326 val sp : Schema [String ] = PrimitiveType .STRING .createProperty().asInstanceOf [Schema [String ]]
2427 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+ }
2732 }
2833 nullSafeList(annotatedType.getCtxAnnotations).foreach {
2934 case p : Parameter => {
@@ -63,12 +68,48 @@ class SwaggerScala3EnumModelConverter extends ModelResolver(Json.mapper()) {
6368
6469 private def isEnum (cls : Class [_]): Boolean = enumEntryClass.isAssignableFrom(cls)
6570
66- private def getValues (cls : Class [_]): Seq [String ] = {
71+ private def tryValues (cls : Class [_]): Try [ Seq [String ]] = Try {
6772 val enumCompanion = Class .forName(cls.getName + " $" ).getField(" MODULE$" ).get(null )
6873 val enumArray = enumCompanion.getClass.getDeclaredMethod(" values" ).invoke(enumCompanion).asInstanceOf [Array [Enum ]]
6974 enumArray.sortBy(_.ordinal).map(_.toString).toSeq
7075 }
7176
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+
72113 private def setRequired (annotatedType : AnnotatedType ): Unit = annotatedType match {
73114 case _ : AnnotatedTypeForOption => // not required
74115 case _ => {
0 commit comments