Skip to content
This repository was archived by the owner on Mar 16, 2025. It is now read-only.

Commit a950c76

Browse files
authored
Merge pull request #46 from openapi-processor/#44
resolves #44
2 parents b2b9316 + e7e3879 commit a950c76

File tree

27 files changed

+466
-113
lines changed

27 files changed

+466
-113
lines changed

src/main/kotlin/io/openapiprocessor/core/converter/DataTypeConverter.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,8 @@ class DataTypeConverter(
181181
}
182182

183183
val constraints = DataTypeConstraints(
184-
nullable = schemaInfo.getNullable()
184+
nullable = schemaInfo.getNullable(),
185+
required = schemaInfo.getRequired()
185186
)
186187

187188
val objectType = ObjectDataType (

src/main/kotlin/io/openapiprocessor/core/converter/SchemaInfo.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ class SchemaInfo(
112112
return schema?.isDeprecated()!!
113113
}
114114

115+
fun getRequired(): List<String> {
116+
return schema?.getRequired()!!
117+
}
118+
115119
/**
116120
* get nullable value.
117121
*

src/main/kotlin/io/openapiprocessor/core/model/Endpoint.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,12 @@ class Endpoint(
7979
// grouped responses
8080
lateinit var endpointResponses: List<EndpointResponse>// = emptyList()
8181

82-
// todo
82+
// todo move to constructor
8383
fun addResponses(httpStatus: String, statusResponses: List<Response>) {
8484
responses[httpStatus] = statusResponses
8585
}
8686

87-
// todo move lists init to constructor then run this from constructor
87+
// todo move addResponse() to constructor then run this from constructor
8888
// fluent
8989
fun initEndpointResponses (): Endpoint {
9090
endpointResponses = createEndpointResponses ()

src/main/kotlin/io/openapiprocessor/core/model/datatypes/DataTypeConstraints.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ class DataTypeConstraints(
1919
var /*val*/ maximum: Number? = null,
2020
var /*val*/ exclusiveMaximum: Boolean = false,
2121
var /*val*/ minItems: Int = 0,
22-
var /*val*/ maxItems: Int? = null
22+
var /*val*/ maxItems: Int? = null,
23+
var /*val*/ required: List<String> = emptyList()
2324

2425
) {
2526

@@ -41,6 +42,10 @@ class DataTypeConstraints(
4142
val maximumConstraint: NumberConstraint
4243
get() = NumberConstraint(maximum!!, exclusiveMaximum)
4344

45+
fun isRequired(prop: String): Boolean {
46+
return required.contains(prop);
47+
}
48+
4449
}
4550

4651
data class SizeConstraints(val min: Int, val max: Int?) {

src/main/kotlin/io/openapiprocessor/core/model/datatypes/ObjectDataType.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,8 @@ class ObjectDataType(
5959
return properties
6060
}
6161

62+
fun isRequired(prop: String): Boolean {
63+
return getConstraints()?.isRequired(prop) ?: false
64+
}
65+
6266
}

src/main/kotlin/io/openapiprocessor/core/parser/Schema.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ interface Schema {
4949
// default false
5050
fun isDeprecated(): Boolean
5151

52+
fun getRequired(): List<String>
53+
5254
// default false
5355
fun getNullable(): Boolean
5456
fun getMinLength(): Int?

src/main/kotlin/io/openapiprocessor/core/parser/openapi4j/Schema.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ class Schema(val schema: O4jSchema) : ParserSchema {
9494

9595
override fun isDeprecated(): Boolean = schema.deprecated ?: false
9696

97+
override fun getRequired(): List<String> = schema.requiredFields ?: emptyList()
98+
9799
override fun getNullable(): Boolean = schema.nullable ?: false
98100

99101
override fun getMinLength(): Int? = schema.minLength ?: 0

src/main/kotlin/io/openapiprocessor/core/parser/swagger/Schema.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ class Schema(private val schema: SwaggerSchema<*>): ParserSchema {
104104

105105
override fun isDeprecated(): Boolean = schema.deprecated ?: false
106106

107+
override fun getRequired(): List<String> = schema.required ?: emptyList()
108+
107109
override fun getNullable(): Boolean = schema.nullable ?: false
108110

109111
override fun getMinLength(): Int? = schema.minLength ?: 0

src/main/kotlin/io/openapiprocessor/core/writer/java/BeanValidationFactory.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ import io.openapiprocessor.core.model.datatypes.*
1212
*/
1313
open class BeanValidationFactory {
1414

15-
fun collectImports(dataType: DataType): Set<String> {
15+
fun collectImports(dataType: DataType, required: Boolean = false): Set<String> {
1616
val imports = mutableSetOf<String>()
1717

1818
if (dataType.isObject()) {
1919
imports.add("javax.validation.Valid")
2020
}
2121

22-
if (dataType.hasNotNullableConstraint()) {
22+
if (required) {
2323
imports.add("javax.validation.constraints.NotNull")
2424
}
2525

@@ -38,14 +38,14 @@ open class BeanValidationFactory {
3838
return imports
3939
}
4040

41-
fun createAnnotations(dataType: DataType): String {
41+
fun createAnnotations(dataType: DataType, required: Boolean = false): String {
4242
val annotations = mutableListOf<String>()
4343

4444
if (dataType.isObject()) {
4545
annotations.add(createValidAnnotation())
4646
}
4747

48-
if (dataType.hasNotNullableConstraint()) {
48+
if (required) {
4949
annotations.add(createNotNullAnnotation())
5050
}
5151

src/main/kotlin/io/openapiprocessor/core/writer/java/DataTypeWriter.kt

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class DataTypeWriter(
5656
propertyNames.forEach {
5757
val javaPropertyName = toCamelCase(it)
5858
val propDataType = dataType.getObjectProperty(it)
59-
target.write(getProp(it, javaPropertyName, propDataType))
59+
target.write(getProp(it, javaPropertyName, propDataType, dataType.isRequired(it)))
6060
}
6161

6262
propertyNames.forEach {
@@ -69,21 +69,23 @@ class DataTypeWriter(
6969
target.write ("}\n")
7070
}
7171

72-
private fun getProp(propertyName: String, javaPropertyName: String, propDataType: DataType): String {
72+
private fun getProp(
73+
propertyName: String, javaPropertyName: String,
74+
propDataType: DataType, required: Boolean): String {
75+
7376
var result = ""
7477
if (propDataType.isDeprecated()) {
7578
result += " @Deprecated\n"
7679
}
7780

78-
result += " @JsonProperty(\"${propertyName}\")\n"
79-
8081
if(apiOptions.beanValidation) {
81-
val beanValidationAnnotations = validationAnnotations.createAnnotations(propDataType)
82-
if (beanValidationAnnotations.isNotEmpty()) {
83-
result += " $beanValidationAnnotations\n"
82+
val annotations = validationAnnotations.createAnnotations(propDataType, required)
83+
if (annotations.isNotEmpty()) {
84+
result += " $annotations\n"
8485
}
8586
}
8687

88+
result += " @JsonProperty(\"${propertyName}\")\n"
8789
result += " private ${propDataType.getName()} ${javaPropertyName};\n\n"
8890
return result
8991
}
@@ -129,8 +131,11 @@ class DataTypeWriter(
129131
imports.addAll(dataType.getReferencedImports())
130132

131133
if (apiOptions.beanValidation) {
132-
dataType.getObjectProperties().values.forEach {
133-
imports.addAll(validationAnnotations.collectImports(it))
134+
val propertyNames = dataType.getObjectProperties().keys
135+
propertyNames.forEach {
136+
val propDataType = dataType.getObjectProperty(it)
137+
imports.addAll(validationAnnotations.collectImports(
138+
propDataType, dataType.isRequired(it)))
134139
}
135140
}
136141

src/main/kotlin/io/openapiprocessor/core/writer/java/InterfaceWriter.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class InterfaceWriter(
7474

7575
ep.parameters.forEach { p ->
7676
if (apiOptions.beanValidation) {
77-
imports.addAll (validationAnnotations.collectImports (p.dataType))
77+
imports.addAll (validationAnnotations.collectImports (p.dataType, p.required))
7878
}
7979

8080
if (p.withAnnotation) {
@@ -92,7 +92,7 @@ class InterfaceWriter(
9292
imports.add (annotations.getAnnotation (b).fullyQualifiedName)
9393
imports.addAll (b.dataTypeImports)
9494
if (apiOptions.beanValidation) {
95-
imports.addAll (validationAnnotations.collectImports (b.dataType))
95+
imports.addAll (validationAnnotations.collectImports (b.dataType, false))
9696
}
9797
}
9898

src/main/kotlin/io/openapiprocessor/core/writer/java/MethodWriter.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ open class MethodWriter(
8787
var methodDefinition = ""
8888

8989
if (apiOptions.beanValidation) {
90-
methodDefinition += " " + beanValidationFactory.createAnnotations(it.dataType)
90+
methodDefinition += " " + beanValidationFactory
91+
.createAnnotations(it.dataType, it.required)
9192
}
9293

9394
val annotation = createParameterAnnotation (it)

src/test/groovy/com/github/hauner/openapi/core/test/AssertHelper.groovy

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import java.util.stream.Collectors
2020

2121
class AssertHelper {
2222

23+
@Deprecated // use io.openapiprocessor.core.extractImports()
2324
static String extractImports (String source) {
2425
source.readLines ().stream ()
2526
.filter {it.startsWith ('import ')}

src/test/groovy/com/github/hauner/openapi/core/test/TestSchema.groovy

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,9 @@ class TestSchema implements Schema {
6262
defaultValue
6363
}
6464

65+
@Override
66+
List<String> getRequired () {
67+
[]
68+
}
69+
6570
}

src/test/groovy/com/github/hauner/openapi/core/writer/java/BeanValidationFactorySpec.groovy

Lines changed: 29 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -47,32 +47,32 @@ class BeanValidationFactorySpec extends Specification {
4747
def dataType = new ObjectDataType('Foo', '', [:], null, false)
4848

4949
when:
50-
def imports = validation.collectImports (dataType)
51-
def annotations = validation.createAnnotations (dataType)
50+
def imports = validation.collectImports (dataType, false)
51+
def annotations = validation.createAnnotations (dataType, false)
5252

5353
then:
5454
imports == resultImports as Set<String>
5555
annotations == resultAnnnotation
5656

5757
where:
5858
resultImports | resultAnnnotation
59-
[VALID, NOT_NULL] | "@Valid @NotNull"
59+
[VALID] | "@Valid"
6060
}
6161

6262
void "does not apply @Valid to non Object types" () {
6363
def dataType = new OtherDataType()
6464

6565
when:
66-
def imports = validation.collectImports (dataType)
67-
def annotations = validation.createAnnotations (dataType)
66+
def imports = validation.collectImports (dataType, false)
67+
def annotations = validation.createAnnotations (dataType, false)
6868

6969
then:
7070
imports == resultImports as Set<String>
7171
annotations == resultAnnnotation
7272

7373
where:
7474
resultImports | resultAnnnotation
75-
[NOT_NULL] | "@NotNull"
75+
[] | ""
7676
}
7777

7878
@Unroll
@@ -85,8 +85,8 @@ class BeanValidationFactorySpec extends Specification {
8585
def dataType = new StringDataType(constraints, false)
8686
8787
when:
88-
def imports = validation.collectImports (dataType)
89-
def annotations = validation.createAnnotations (dataType)
88+
def imports = validation.collectImports (dataType, false)
89+
def annotations = validation.createAnnotations (dataType, false)
9090
9191
then:
9292
containsImports (imports, resultImports)
@@ -116,8 +116,8 @@ class BeanValidationFactorySpec extends Specification {
116116
DataType dataType = new ArrayDataType(new NoneDataType(), constraints, false)
117117
118118
when:
119-
def imports = validation.collectImports (dataType)
120-
def annotations = validation.createAnnotations (dataType)
119+
def imports = validation.collectImports (dataType, false)
120+
def annotations = validation.createAnnotations (dataType, false)
121121
122122
then:
123123
imports.containsAll (resultImports)
@@ -152,8 +152,8 @@ class BeanValidationFactorySpec extends Specification {
152152
false)
153153
154154
when:
155-
def imports = validation.collectImports (dataType)
156-
def annotations = validation.createAnnotations (dataType)
155+
def imports = validation.collectImports (dataType, false)
156+
def annotations = validation.createAnnotations (dataType, false)
157157
158158
then:
159159
imports.containsAll (resultImports)
@@ -174,33 +174,25 @@ class BeanValidationFactorySpec extends Specification {
174174
}
175175
176176
@Unroll
177-
void "applies @NotNull (nullable: #nullable, type: #type)" () {
178-
def constraints = new DataTypeConstraints (
179-
nullable: nullable
180-
)
181-
182-
DataType dataType = createDataType (type, constraints)
177+
void "applies @NotNull (required: #required, type: #type)" () {
178+
DataType dataType = createDataType (type, new DataTypeConstraints ())
183179
184180
when:
185-
def imports = validation.collectImports (dataType)
186-
def annotations = validation.createAnnotations (dataType)
181+
def imports = validation.collectImports (dataType, required)
182+
def annotations = validation.createAnnotations (dataType, required)
187183
188184
then:
189185
imports.containsAll (resultImports)
190186
annotations.contains (resultAnnotations)
191187
192188
where:
193-
type | nullable || resultImports | resultAnnotations
194-
// nullable defaults to false if not set
195-
// IntegerDataType | null || [] | ""
196-
IntegerDataType | true || [] | ""
197-
IntegerDataType | false || [NOT_NULL] | "@NotNull"
198-
// StringDataType | null || [] | ""
199-
StringDataType | true || [] | ""
200-
StringDataType | false || [NOT_NULL] | "@NotNull"
201-
// MappedCollectionDataType | null || [] | ""
202-
MappedCollectionDataType | true || [] | ""
203-
MappedCollectionDataType | false || [NOT_NULL] | "@NotNull"
189+
type | required || resultImports | resultAnnotations
190+
IntegerDataType | false || [] | ""
191+
IntegerDataType | true || [NOT_NULL] | "@NotNull"
192+
StringDataType | false || [] | ""
193+
StringDataType | true || [NOT_NULL] | "@NotNull"
194+
MappedCollectionDataType | false || [] | ""
195+
MappedCollectionDataType | true || [NOT_NULL] | "@NotNull"
204196
}
205197

206198
@Unroll
@@ -213,8 +205,8 @@ class BeanValidationFactorySpec extends Specification {
213205
DataType dataType = createDataType (type, constraints)
214206

215207
when:
216-
def imports = validation.collectImports (dataType)
217-
def annotations = validation.createAnnotations (dataType)
208+
def imports = validation.collectImports (dataType, false)
209+
def annotations = validation.createAnnotations (dataType, false)
218210

219211
then:
220212
imports.containsAll (resultImports)
@@ -261,8 +253,8 @@ class BeanValidationFactorySpec extends Specification {
261253
DataType dataType = createDataType (type, constraints)
262254

263255
when:
264-
def imports = validation.collectImports (dataType)
265-
def annotations = validation.createAnnotations (dataType)
256+
def imports = validation.collectImports (dataType, false)
257+
def annotations = validation.createAnnotations (dataType, false)
266258

267259
then:
268260
imports.containsAll (resultImports)
@@ -310,8 +302,8 @@ class BeanValidationFactorySpec extends Specification {
310302
DataType dataType = new DoubleDataType (constraints, false)
311303

312304
when:
313-
def imports = validation.collectImports (dataType)
314-
def annotations = validation.createAnnotations (dataType)
305+
def imports = validation.collectImports (dataType, false)
306+
def annotations = validation.createAnnotations (dataType, false)
315307

316308
then:
317309
imports.containsAll (resultImports)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright © 2019 https://github.com/openapi-processor/openapi-processor-core
3+
* PDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.openapiprocessor.core.support
7+
8+
import io.openapiprocessor.core.model.Endpoint
9+
import io.openapiprocessor.core.model.EndpointResponse
10+
import io.openapiprocessor.core.writer.java.MappingAnnotationWriter
11+
import java.io.Writer
12+
13+
class TestMappingAnnotationWriter: MappingAnnotationWriter {
14+
15+
override fun write(target: Writer, endpoint: Endpoint, endpointResponse: EndpointResponse) {
16+
target.write ("@CoreMapping")
17+
}
18+
19+
}

0 commit comments

Comments
 (0)