Skip to content

Commit e9a41ff

Browse files
committed
openapi-processor/openapi-processor-spring#198, generate enum values validator
1 parent f7269a7 commit e9a41ff

4 files changed

Lines changed: 113 additions & 12 deletions

File tree

openapi-processor-core/src/main/kotlin/io/openapiprocessor/core/writer/java/ApiWriter.kt

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import java.io.Writer
2424
class ApiWriter(
2525
private val options: ApiOptions,
2626
private val generatedWriter: GeneratedWriter,
27+
private val validationWriter: ValidationWriter,
2728
private val interfaceWriter: InterfaceWriter,
2829
private val dataTypeWriter: DataTypeWriter,
2930
private val enumWriter: StringEnumWriter,
@@ -37,9 +38,9 @@ class ApiWriter(
3738
}
3839
}
3940

40-
4141
fun write(api: Api) {
4242
writeGenerated()
43+
writeValidation()
4344
writeInterfaces(api)
4445
writeObjectDataTypes(api)
4546
writeInterfaceDataTypes(api)
@@ -52,6 +53,19 @@ class ApiWriter(
5253
writer.close()
5354
}
5455

56+
private fun writeValidation() {
57+
if (!options.beanValidation)
58+
return
59+
60+
val vWriter = getWriter("${options.packageName}.validation", "Values")
61+
writeValues(vWriter)
62+
vWriter.close()
63+
64+
val vvWriter = getWriter("${options.packageName}.validation", "ValueValidator")
65+
writeValueValidator(vvWriter)
66+
vvWriter.close()
67+
}
68+
5569
private fun writeInterfaces(api: Api) {
5670
api.forEachInterface {
5771
val writer = getWriter(it.getPackageName(), it.getInterfaceName())
@@ -114,6 +128,18 @@ class ApiWriter(
114128
writer.write(format(raw.toString()))
115129
}
116130

131+
private fun writeValues(writer: Writer) {
132+
val raw = StringWriter()
133+
validationWriter.writeValues(raw)
134+
writer.write(format(raw.toString()))
135+
}
136+
137+
private fun writeValueValidator(writer: Writer) {
138+
val raw = StringWriter()
139+
validationWriter.writeValueValidator(raw)
140+
writer.write(format(raw.toString()))
141+
}
142+
117143
private fun getWriter(packageName: String, className: String): Writer {
118144
return writerFactory.createWriter(packageName, className)
119145
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright 2023 https://github.com/openapi-processor/openapi-processor-base
3+
* PDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.openapiprocessor.core.writer.java
7+
8+
import io.openapiprocessor.core.converter.ApiOptions
9+
import java.io.Writer
10+
11+
class ValidationWriter(val options: ApiOptions) {
12+
13+
fun writeValues(target: Writer) {
14+
target.write("""
15+
package ${options.packageName}.validation;
16+
17+
import ${options.beanValidationFormat}.validation.Constraint;
18+
import ${options.beanValidationFormat}.validation.Payload;
19+
import java.lang.annotation.*;
20+
21+
@Target({ElementType.FIELD, ElementType.PARAMETER})
22+
@Retention(RetentionPolicy.RUNTIME)
23+
@Constraint(validatedBy = ValueValidator.class)
24+
@Documented
25+
public @interface Values {
26+
String message() default "Invalid value. Should be one of values.";
27+
Class<?>[] groups() default {};
28+
Class<? extends Payload>[] payload() default {};
29+
String[] values() default {};
30+
}
31+
32+
""".trimIndent())
33+
}
34+
35+
fun writeValueValidator(target: Writer) {
36+
target.write("""
37+
package ${options.packageName}.validation;
38+
39+
import jakarta.validation.ConstraintValidator;
40+
import jakarta.validation.ConstraintValidatorContext;
41+
42+
import java.util.Arrays;
43+
44+
public class ValueValidator implements ConstraintValidator<Values, String> {
45+
private String[] values;
46+
47+
@Override
48+
public void initialize (Values constraintAnnotation) {
49+
values = constraintAnnotation.values();
50+
}
51+
52+
@Override
53+
public boolean isValid (String value, ConstraintValidatorContext context) {
54+
return value != null && Arrays.asList(values).contains(value);
55+
}
56+
}
57+
58+
""".trimIndent())
59+
}
60+
}

openapi-processor-core/src/test/kotlin/io/openapiprocessor/core/writer/java/ApiWriterSpec.kt

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020 https://github.com/openapi-processor/openapi-processor-core
2+
* Copyright 2020 https://github.com/openapi-processor/openapi-processor-base
33
* PDX-License-Identifier: Apache-2.0
44
*/
55

@@ -55,7 +55,7 @@ class ApiWriterSpec: StringSpec({
5555
val api = Api(dataTypes = dts)
5656

5757
val enumWriter = stub<StringEnumWriter>(relaxed = true)
58-
ApiWriter(options, stub(relaxed = true), stub(), stub(), enumWriter, stub(), nf, wfStub)
58+
ApiWriter(options, stub(relaxed = true), stub(), stub(), stub(), enumWriter, stub(), nf, wfStub)
5959
.write(api)
6060

6161
verify(exactly = 1) { enumWriter.write(any(), dtA) }
@@ -70,7 +70,7 @@ class ApiWriterSpec: StringSpec({
7070
dts.addRef("Foo")
7171
val api = Api(dataTypes = dts)
7272

73-
ApiWriter(options, stub(relaxed = true), stub(), stub(), stub(relaxed = true), stub(), formatter, wfStub)
73+
ApiWriter(options, stub(relaxed = true), stub(), stub(), stub(), stub(relaxed = true), stub(), formatter, wfStub)
7474
.write(api)
7575

7676
verify (exactly = 2) { formatter.format(any()) }
@@ -84,7 +84,7 @@ class ApiWriterSpec: StringSpec({
8484
val api = Api(itfs)
8585

8686
val itfWriter = stub<InterfaceWriter>(relaxed = true)
87-
ApiWriter(options, stub(relaxed = true), itfWriter, stub(), stub(), stub(), nf, wfStub)
87+
ApiWriter(options, stub(relaxed = true), stub(), itfWriter, stub(), stub(), stub(), nf, wfStub)
8888
.write (api)
8989

9090
verify(exactly = 1) { itfWriter.write(any(), itfs[0]) }
@@ -99,7 +99,7 @@ class ApiWriterSpec: StringSpec({
9999
)
100100
val api = Api(itfs)
101101

102-
ApiWriter(options, stub(relaxed = true), stub(relaxed = true), stub(), stub(), stub(), formatter, wfStub)
102+
ApiWriter(options, stub(relaxed = true), stub(), stub(relaxed = true), stub(), stub(), stub(), formatter, wfStub)
103103
.write(api)
104104

105105
verify (exactly = 2) { formatter.format(any()) }
@@ -119,7 +119,7 @@ class ApiWriterSpec: StringSpec({
119119
val api = Api(dataTypes = dts)
120120

121121
val dtWriter = stub<DataTypeWriter>(relaxed = true)
122-
ApiWriter(options, stub(relaxed = true), stub(), dtWriter, stub(), stub(), nf, wfStub)
122+
ApiWriter(options, stub(relaxed = true), stub(), stub(), dtWriter, stub(), stub(), nf, wfStub)
123123
.write (api)
124124

125125
verify(exactly = 1) { dtWriter.write(any(), dtA) }
@@ -134,7 +134,7 @@ class ApiWriterSpec: StringSpec({
134134
dts.addRef("Foo")
135135
val api = Api(dataTypes = dts)
136136

137-
ApiWriter(options, stub(relaxed = true), stub(), stub(relaxed = true), stub(), stub(), formatter, wfStub)
137+
ApiWriter(options, stub(relaxed = true), stub(), stub(), stub(relaxed = true), stub(), stub(), formatter, wfStub)
138138
.write(api)
139139

140140
verify (exactly = 2) { formatter.format(any()) }
@@ -154,7 +154,7 @@ class ApiWriterSpec: StringSpec({
154154
val api = Api(dataTypes = dts)
155155

156156
val dtWriter = stub<InterfaceDataTypeWriter>(relaxed = true)
157-
ApiWriter(options, stub(relaxed = true), stub(), stub(), stub(), dtWriter, nf, wfStub)
157+
ApiWriter(options, stub(relaxed = true), stub(), stub(), stub(), stub(), dtWriter, nf, wfStub)
158158
.write (api)
159159

160160
verify(exactly = 1) { dtWriter.write(any(), dtA) }
@@ -169,7 +169,7 @@ class ApiWriterSpec: StringSpec({
169169
dts.addRef("Foo")
170170
val api = Api(dataTypes = dts)
171171

172-
ApiWriter(options, stub(relaxed = true), stub(), stub(), stub(), stub(relaxed = true), formatter, wfStub)
172+
ApiWriter(options, stub(relaxed = true), stub(), stub(), stub(), stub(), stub(relaxed = true), formatter, wfStub)
173173
.write(api)
174174

175175
verify (exactly = 2) { formatter.format(any()) }
@@ -184,7 +184,7 @@ class ApiWriterSpec: StringSpec({
184184
val api = Api(dataTypes = dt)
185185

186186
// when:
187-
ApiWriter(options, gwStub, stub(), dtWriter, stub(), stub()).write (api)
187+
ApiWriter(options, gwStub, stub(), stub(), dtWriter, stub(), stub()).write (api)
188188

189189
// then:
190190
verify(exactly = 0) {
@@ -201,11 +201,25 @@ class ApiWriterSpec: StringSpec({
201201
val api = Api(dataTypes = dts)
202202

203203
options.formatCode = false
204-
ApiWriter(options, stub(relaxed = true), stub(), stub(), stub(), stub(relaxed = true), formatter, wfStub)
204+
ApiWriter(options, stub(relaxed = true), stub(), stub(), stub(), stub(), stub(relaxed = true), formatter, wfStub)
205205
.write(api)
206206

207207
verify (exactly = 0) { formatter.format(any()) }
208208
}
209+
210+
"writes custom validation sources" {
211+
val validation = stub<ValidationWriter>(relaxed = true)
212+
213+
val dts = DataTypes()
214+
options.beanValidation = true
215+
val api = Api(dataTypes = dts)
216+
217+
ApiWriter(options, stub(relaxed = true), validation, stub(), stub(), stub(), stub(), nf, wfStub)
218+
.write(api)
219+
220+
verify(exactly = 1) { validation.writeValues(any()) }
221+
verify(exactly = 1) { validation.writeValueValidator(any()) }
222+
}
209223
})
210224

211225
private fun ApiOptions.getSourceDir(pkg: String): Path {

openapi-processor-core/src/testInt/kotlin/io/openapiprocessor/core/TestProcessor.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class TestProcessor:
5252
val writer = ApiWriter(
5353
options,
5454
generatedWriter,
55+
ValidationWriter(options),
5556
InterfaceWriter(
5657
options,
5758
generatedWriter,

0 commit comments

Comments
 (0)