Skip to content

Commit 170099e

Browse files
committed
GH-249 Support OpenApiByFields(only = true) (Resolve #249)
1 parent caf9a00 commit 170099e

File tree

5 files changed

+47
-14
lines changed

5 files changed

+47
-14
lines changed

examples/javalin-gradle-kotlin/src/main/java/io/javalin/openapi/plugin/test/JavalinTest.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ public static void main(String[] args) {
162162
@OpenApiContent(from = LombokEntity.class, mimeType = "app/lombok"), // lombok
163163
@OpenApiContent(from = EntityWithGenericType.class), // generics
164164
@OpenApiContent(from = RecordEntity.class, mimeType = "app/record"), // record class
165-
@OpenApiContent(from = DtoWithFields.class, mimeType = "app/dto"), // map only fields
165+
@OpenApiContent(from = DtoWithFields.class, mimeType = "app/dto-fields"), // map only fields
166+
@OpenApiContent(from = DtoWithFieldsAndMethods.class, mimeType = "app/dto-fields-and-methods"), // map fields and methods
166167
@OpenApiContent(from = EnumEntity.class, mimeType = "app/enum"), // enum,
167168
@OpenApiContent(from = CustomNameEntity.class, mimeType = "app/custom-name-entity") // custom name
168169
}
@@ -470,13 +471,31 @@ record RecordEntity(
470471
) {}
471472

472473
// should query fields
473-
@OpenApiByFields(Visibility.PROTECTED) // by default: PUBLIC
474+
@OpenApiByFields(value = Visibility.PROTECTED, only = true) // by default: PUBLIC
474475
static final class DtoWithFields {
475476

476477
public String publicName;
477478
String defaultName;
478479
protected String protectedName;
479480
private String privateName;
481+
482+
public String getCustom() {
483+
return "custom";
484+
}
485+
}
486+
487+
// should query fields and methods
488+
@OpenApiByFields(Visibility.PROTECTED) // by default: PUBLIC
489+
static final class DtoWithFieldsAndMethods {
490+
491+
public String publicName;
492+
String defaultName;
493+
protected String protectedName;
494+
private String privateName;
495+
496+
public String getCustom() {
497+
return "custom";
498+
}
480499
}
481500

482501
enum EnumEntity {

openapi-annotation-processor/src/test/kotlin/io/javalin/openapi/processor/TypeMappersTest.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ internal class TypeMappersTest : OpenApiAnnotationProcessorSpecification() {
2121

2222
class CustomType // mapped by openapi.groovy
2323

24+
enum class StandardEnum {
25+
VALUE_1,
26+
VALUE_2,
27+
}
28+
29+
enum class CapitalizedFirstLetterEnum {
30+
Value1,
31+
Value2,
32+
}
33+
2434
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "RemoveRedundantQualifierName")
2535
class SimpleTypesList(
2636
val customType: CustomType,
@@ -53,7 +63,9 @@ internal class TypeMappersTest : OpenApiAnnotationProcessorSpecification() {
5363
val instant: Instant,
5464
val obj: Object,
5565
val map: Map<*, *>,
56-
val mapWithList: Map<*, List<*>>
66+
val mapWithList: Map<*, List<*>>,
67+
val standardEnum: StandardEnum,
68+
val capitalizedFirstLetterEnum: CapitalizedFirstLetterEnum,
5769
)
5870

5971
@OpenApi(

openapi-specification/src/main/kotlin/io/javalin/openapi/OpenApiAnnotations.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,10 +308,13 @@ enum class Visibility(val priority: Int) {
308308
PRIVATE(1)
309309
}
310310

311+
/** Fields with the specified visibility or higher will be included in the schema */
311312
@Target(CLASS)
312313
@Retention(RUNTIME)
313314
annotation class OpenApiByFields(
314-
val value: Visibility = PUBLIC
315+
val value: Visibility = PUBLIC,
316+
/** If true, methods will be ignored */
317+
val only: Boolean = false,
315318
)
316319

317320
/** Null class because annotations do not support null values */

openapi-specification/src/main/kotlin/io/javalin/openapi/experimental/processor/generators/TypeSchemaGenerator.kt

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ import javax.lang.model.element.AnnotationMirror
3737
import javax.lang.model.element.AnnotationValue
3838
import javax.lang.model.element.AnnotationValueVisitor
3939
import javax.lang.model.element.Element
40-
import javax.lang.model.element.ElementKind.ENUM
41-
import javax.lang.model.element.ElementKind.METHOD
40+
import javax.lang.model.element.ElementKind.*
4241
import javax.lang.model.element.ExecutableElement
4342
import javax.lang.model.element.Modifier
4443
import javax.lang.model.element.VariableElement
@@ -75,7 +74,6 @@ class TypeSchemaGenerator(val context: AnnotationProcessorContext) {
7574
composition != null -> {
7675
schema.createComposition(context, type, composition, references, inlineRefs, requireNonNullsByDefault)
7776
}
78-
7977
source.kind == ENUM -> {
8078
val values = JsonArray()
8179
source.enclosedElements
@@ -88,7 +86,6 @@ class TypeSchemaGenerator(val context: AnnotationProcessorContext) {
8886
schema.addProperty("type", "string")
8987
schema.add("enum", values)
9088
}
91-
9289
else -> {
9390
schema.addProperty("type", "object")
9491
schema.addProperty("additionalProperties", false)
@@ -209,8 +206,7 @@ data class Property(
209206
)
210207

211208
internal fun ClassDefinition.findAllProperties(requireNonNulls: Boolean): Collection<Property> = context.inContext {
212-
val acceptFields = source.getAnnotation(OpenApiByFields::class.java)
213-
?.value
209+
val openApiByFields: OpenApiByFields? = source.getAnnotation(OpenApiByFields::class.java)
214210

215211
val isRecord = when (recordType()) {
216212
null -> false
@@ -230,10 +226,13 @@ internal fun ClassDefinition.findAllProperties(requireNonNulls: Boolean): Collec
230226
continue
231227
}
232228

233-
if (property.kind != METHOD && acceptFields == null) {
234-
continue
229+
when {
230+
property.kind != METHOD && openApiByFields == null -> continue
231+
property.kind == METHOD && openApiByFields?.only == true -> continue
235232
}
236233

234+
val acceptFields = openApiByFields?.value
235+
237236
if (acceptFields != null) {
238237
val modifiers = property.modifiers
239238

@@ -263,7 +262,7 @@ internal fun ClassDefinition.findAllProperties(requireNonNulls: Boolean): Collec
263262

264263
val name = when {
265264
customName != null -> customName.value
266-
isRecord || acceptFields != null -> simpleName
265+
isRecord || property.kind == FIELD -> simpleName
267266
simpleName.startsWith("get") -> simpleName.replaceFirst("get", "").replaceFirstChar { it.lowercase() }
268267
simpleName.startsWith("is") -> simpleName.replaceFirst("is", "").replaceFirstChar { it.lowercase() }
269268
else -> continue

wiki

Submodule wiki updated from 866a4ca to f7a1849

0 commit comments

Comments
 (0)