Skip to content

Commit 1d9fcb3

Browse files
kliebermduesterhoeft
authored andcommitted
Extract generator into separate library (#39)
1 parent 506ad3a commit 1d9fcb3

File tree

15 files changed

+130
-106
lines changed

15 files changed

+130
-106
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
2+
3+
plugins {
4+
kotlin("jvm")
5+
}
6+
7+
repositories {
8+
mavenCentral()
9+
jcenter()
10+
maven { url = uri("https://jitpack.io") }
11+
}
12+
13+
dependencies {
14+
compile(kotlin("stdlib-jdk8"))
15+
16+
compile("io.swagger:swagger-core:1.5.20")
17+
compile("com.fasterxml.jackson.core:jackson-databind:2.9.5")
18+
compile("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.5")
19+
compile("com.github.everit-org.json-schema:org.everit.json.schema:1.9.1")
20+
21+
testImplementation("io.swagger:swagger-parser:1.0.36")
22+
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.2.0")
23+
testImplementation("org.assertj:assertj-core:3.10.0")
24+
25+
testImplementation("org.amshove.kluent:kluent:1.35")
26+
testImplementation("com.jayway.jsonpath:json-path:2.4.0")
27+
testImplementation("com.github.java-json-tools:json-schema-validator:2.2.10")
28+
}
29+
30+
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
package com.epages.restdocs.openapi.gradle
1+
package com.epages.restdocs.openapi.generator
22

33
import io.swagger.models.Swagger
44
import io.swagger.util.Json
55
import io.swagger.util.Yaml
66
import java.io.File
77

8-
internal object ApiSpecificationWriter {
8+
object ApiSpecificationWriter {
99

1010
private val yamlFormats = setOf("yaml", "yml")
1111
private val jsonFormats = setOf("json")
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.epages.restdocs.openapi.generator
2+
3+
import java.io.File
4+
5+
class Oauth2Configuration(
6+
var tokenUrl: String = "", // required for types "password", "application", "accessCode"
7+
var authorizationUrl: String = "", // required for the "accessCode" type
8+
var flows: Array<String> = arrayOf(),
9+
var scopeDescriptionsPropertiesFile: String? = null,
10+
var scopeDescriptionsPropertiesProjectFile: File? = null
11+
) {
12+
fun securitySchemeName(flow: String) = "oauth2_$flow"
13+
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
package com.epages.restdocs.openapi.gradle
1+
package com.epages.restdocs.openapi.generator
22

3-
import com.epages.restdocs.openapi.gradle.schema.JsonSchemaFromFieldDescriptorsGenerator
3+
import com.epages.restdocs.openapi.generator.schema.JsonSchemaFromFieldDescriptorsGenerator
44
import com.fasterxml.jackson.databind.ObjectMapper
55
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
66
import com.fasterxml.jackson.module.kotlin.readValue
@@ -24,7 +24,7 @@ import io.swagger.util.Json
2424
import java.util.Comparator.comparing
2525
import java.util.Comparator.comparingInt
2626

27-
internal object OpenApi20Generator {
27+
object OpenApi20Generator {
2828

2929
private val objectMapper = ObjectMapper(YAMLFactory())
3030

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
package com.epages.restdocs.openapi.gradle
1+
package com.epages.restdocs.openapi.generator
22

3-
internal data class ResourceModel(
3+
data class ResourceModel(
44
val operationId: String,
55
val summary: String? = null,
66
val description: String? = null,
@@ -10,7 +10,7 @@ internal data class ResourceModel(
1010
val response: ResponseModel
1111
)
1212

13-
internal data class RequestModel(
13+
data class RequestModel(
1414
val path: String,
1515
val method: HTTPMethod,
1616
val contentType: String? = null,
@@ -23,7 +23,7 @@ internal data class RequestModel(
2323
val schema: String? = null
2424
)
2525

26-
internal data class ResponseModel(
26+
data class ResponseModel(
2727
val status: Int,
2828
val contentType: String?,
2929
val headers: List<HeaderDescriptor>,
@@ -32,7 +32,7 @@ internal data class ResponseModel(
3232
val schema: String? = null
3333
)
3434

35-
internal enum class SimpleType {
35+
enum class SimpleType {
3636
STRING,
3737
INTEGER,
3838
NUMBER,
@@ -46,14 +46,14 @@ interface AbstractParameterDescriptor {
4646
val optional: Boolean
4747
}
4848

49-
internal data class HeaderDescriptor(
49+
data class HeaderDescriptor(
5050
override val name: String,
5151
override val description: String,
5252
override val type: String,
5353
override val optional: Boolean
5454
) : AbstractParameterDescriptor
5555

56-
internal open class FieldDescriptor(
56+
open class FieldDescriptor(
5757
val path: String,
5858
val description: String,
5959
val type: String,
@@ -62,35 +62,35 @@ internal open class FieldDescriptor(
6262
val attributes: Attributes = Attributes()
6363
)
6464

65-
internal data class Attributes(
65+
data class Attributes(
6666
val validationConstraints: List<Constraint> = emptyList()
6767
)
6868

69-
internal data class Constraint(
69+
data class Constraint(
7070
val name: String,
7171
val configuration: Map<String, Any>
7272
)
7373

74-
internal data class ParameterDescriptor(
74+
data class ParameterDescriptor(
7575
override val name: String,
7676
override val description: String,
7777
override val type: String,
7878
override val optional: Boolean,
7979
val ignored: Boolean
8080
) : AbstractParameterDescriptor
8181

82-
internal data class SecurityRequirements(
82+
data class SecurityRequirements(
8383
val type: SecurityType,
8484
val requiredScopes: List<String>?
8585
)
8686

87-
internal enum class SecurityType {
87+
enum class SecurityType {
8888
OAUTH2,
8989
BASIC,
9090
API_KEY
9191
}
9292

93-
internal enum class HTTPMethod {
93+
enum class HTTPMethod {
9494
GET,
9595
POST,
9696
PUT,
Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
package com.epages.restdocs.openapi.gradle.schema
2-
3-
import com.epages.restdocs.openapi.gradle.Constraint
4-
import com.epages.restdocs.openapi.gradle.FieldDescriptor
1+
package com.epages.restdocs.openapi.generator.schema
52

63
internal object ConstraintResolver {
74

@@ -22,7 +19,7 @@ internal object ConstraintResolver {
2219

2320
private const val LENGTH_CONSTRAINT = "org.hibernate.validator.constraints.Length"
2421

25-
internal fun minLengthString(fieldDescriptor: com.epages.restdocs.openapi.gradle.FieldDescriptor): Int? {
22+
internal fun minLengthString(fieldDescriptor: com.epages.restdocs.openapi.generator.FieldDescriptor): Int? {
2623
return findConstraints(fieldDescriptor)
2724
.firstOrNull { constraint ->
2825
(NOT_EMPTY_CONSTRAINTS.contains(constraint.name) ||
@@ -32,16 +29,16 @@ internal object ConstraintResolver {
3229
?.let { constraint -> if (LENGTH_CONSTRAINT == constraint.name) constraint.configuration["min"] as Int else 1 }
3330
}
3431

35-
internal fun maxLengthString(fieldDescriptor: com.epages.restdocs.openapi.gradle.FieldDescriptor): Int? {
32+
internal fun maxLengthString(fieldDescriptor: com.epages.restdocs.openapi.generator.FieldDescriptor): Int? {
3633
return findConstraints(fieldDescriptor)
3734
.firstOrNull { LENGTH_CONSTRAINT == it.name }
3835
?.let { it.configuration["max"] as Int }
3936
}
4037

41-
internal fun isRequired(fieldDescriptor: com.epages.restdocs.openapi.gradle.FieldDescriptor): Boolean =
38+
internal fun isRequired(fieldDescriptor: com.epages.restdocs.openapi.generator.FieldDescriptor): Boolean =
4239
findConstraints(fieldDescriptor)
4340
.any { constraint -> REQUIRED_CONSTRAINTS.contains(constraint.name) }
4441

45-
private fun findConstraints(fieldDescriptor: com.epages.restdocs.openapi.gradle.FieldDescriptor): List<com.epages.restdocs.openapi.gradle.Constraint> =
42+
private fun findConstraints(fieldDescriptor: com.epages.restdocs.openapi.generator.FieldDescriptor): List<com.epages.restdocs.openapi.generator.Constraint> =
4643
fieldDescriptor.attributes.validationConstraints
4744
}
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
package com.epages.restdocs.openapi.gradle.schema
1+
package com.epages.restdocs.openapi.generator.schema
22

3-
import com.epages.restdocs.openapi.gradle.schema.JsonSchemaFromFieldDescriptorsGenerator.FieldDescriptorWithSchemaType
43
import java.util.ArrayList
54
import java.util.regex.Pattern
65

76
internal class JsonFieldPath private constructor(
87
private val segments: List<String>,
9-
val fieldDescriptor: FieldDescriptorWithSchemaType
8+
val fieldDescriptor: JsonSchemaFromFieldDescriptorsGenerator.FieldDescriptorWithSchemaType
109
) {
1110

1211
fun remainingSegments(traversedSegments: List<String>): List<String> {
@@ -31,7 +30,7 @@ internal class JsonFieldPath private constructor(
3130
private val ARRAY_INDEX_PATTERN = Pattern
3231
.compile("\\[([0-9]+|\\*){0,1}\\]")
3332

34-
fun compile(descriptor: FieldDescriptorWithSchemaType): JsonFieldPath {
33+
fun compile(descriptor: JsonSchemaFromFieldDescriptorsGenerator.FieldDescriptorWithSchemaType): JsonFieldPath {
3534
val segments = extractSegments(descriptor.path)
3635
return JsonFieldPath(segments, descriptor)
3736
}
Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
package com.epages.restdocs.openapi.gradle.schema
1+
package com.epages.restdocs.openapi.generator.schema
22

3-
import com.epages.restdocs.openapi.gradle.schema.ConstraintResolver.isRequired
4-
import com.epages.restdocs.openapi.gradle.schema.ConstraintResolver.maxLengthString
5-
import com.epages.restdocs.openapi.gradle.schema.ConstraintResolver.minLengthString
3+
import com.epages.restdocs.openapi.generator.schema.ConstraintResolver.isRequired
4+
import com.epages.restdocs.openapi.generator.schema.ConstraintResolver.maxLengthString
5+
import com.epages.restdocs.openapi.generator.schema.ConstraintResolver.minLengthString
66
import com.fasterxml.jackson.databind.SerializationFeature
77
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
88
import org.everit.json.schema.ArraySchema
@@ -22,9 +22,9 @@ import java.util.function.Predicate
2222

2323
internal class JsonSchemaFromFieldDescriptorsGenerator {
2424

25-
internal fun generateSchema(fieldDescriptors: List<com.epages.restdocs.openapi.gradle.FieldDescriptor>, title: String? = null): String {
25+
internal fun generateSchema(fieldDescriptors: List<com.epages.restdocs.openapi.generator.FieldDescriptor>, title: String? = null): String {
2626
val jsonFieldPaths = reduceFieldDescriptors(fieldDescriptors)
27-
.map { com.epages.restdocs.openapi.gradle.schema.JsonFieldPath.compile(it) }
27+
.map { com.epages.restdocs.openapi.generator.schema.JsonFieldPath.compile(it) }
2828

2929
val schema = traverse(emptyList(), jsonFieldPaths, ObjectSchema.builder().title(title) as ObjectSchema.Builder)
3030

@@ -36,7 +36,7 @@ internal class JsonSchemaFromFieldDescriptorsGenerator {
3636
*
3737
* The implementation will
3838
*/
39-
private fun reduceFieldDescriptors(fieldDescriptors: List<com.epages.restdocs.openapi.gradle.FieldDescriptor>): List<FieldDescriptorWithSchemaType> {
39+
private fun reduceFieldDescriptors(fieldDescriptors: List<com.epages.restdocs.openapi.generator.FieldDescriptor>): List<FieldDescriptorWithSchemaType> {
4040
return fieldDescriptors
4141
.map { FieldDescriptorWithSchemaType.fromFieldDescriptor(it) }
4242
.foldRight(listOf()) { fieldDescriptor, groups -> groups
@@ -48,7 +48,7 @@ internal class JsonSchemaFromFieldDescriptorsGenerator {
4848
}
4949
}
5050

51-
private fun unWrapRootArray(jsonFieldPaths: List<com.epages.restdocs.openapi.gradle.schema.JsonFieldPath>, schema: Schema): Schema {
51+
private fun unWrapRootArray(jsonFieldPaths: List<com.epages.restdocs.openapi.generator.schema.JsonFieldPath>, schema: Schema): Schema {
5252
if (schema is ObjectSchema) {
5353
val groups = groupFieldsByFirstRemainingPathSegment(emptyList(), jsonFieldPaths)
5454
if (groups.keys.size == 1 && groups.keys.contains("[]")) {
@@ -68,7 +68,7 @@ internal class JsonSchemaFromFieldDescriptorsGenerator {
6868

6969
private fun traverse(
7070
traversedSegments: List<String>,
71-
jsonFieldPaths: List<com.epages.restdocs.openapi.gradle.schema.JsonFieldPath>,
71+
jsonFieldPaths: List<com.epages.restdocs.openapi.generator.schema.JsonFieldPath>,
7272
builder: ObjectSchema.Builder
7373
): Schema {
7474

@@ -102,30 +102,30 @@ internal class JsonSchemaFromFieldDescriptorsGenerator {
102102
return builder.build()
103103
}
104104

105-
private fun isDirectMatch(traversedSegments: List<String>): Predicate<com.epages.restdocs.openapi.gradle.schema.JsonFieldPath> {
105+
private fun isDirectMatch(traversedSegments: List<String>): Predicate<com.epages.restdocs.openapi.generator.schema.JsonFieldPath> {
106106
// we have a direct match when there are no remaining segments or when the only following element is an array
107107
return Predicate { jsonFieldPath ->
108108
val remainingSegments = jsonFieldPath.remainingSegments(traversedSegments)
109-
remainingSegments.isEmpty() || remainingSegments.size == 1 && com.epages.restdocs.openapi.gradle.schema.JsonFieldPath.isArraySegment(remainingSegments[0])
109+
remainingSegments.isEmpty() || remainingSegments.size == 1 && com.epages.restdocs.openapi.generator.schema.JsonFieldPath.isArraySegment(remainingSegments[0])
110110
}
111111
}
112112

113113
private fun groupFieldsByFirstRemainingPathSegment(
114114
traversedSegments: List<String>,
115-
jsonFieldPaths: List<com.epages.restdocs.openapi.gradle.schema.JsonFieldPath>
116-
): Map<String, List<com.epages.restdocs.openapi.gradle.schema.JsonFieldPath>> {
115+
jsonFieldPaths: List<com.epages.restdocs.openapi.generator.schema.JsonFieldPath>
116+
): Map<String, List<com.epages.restdocs.openapi.generator.schema.JsonFieldPath>> {
117117
return jsonFieldPaths.groupBy { it.remainingSegments(traversedSegments)[0] }
118118
}
119119

120120
private fun processRemainingSegments(
121121
builder: ObjectSchema.Builder,
122122
propertyName: String,
123123
traversedSegments: MutableList<String>,
124-
fields: List<com.epages.restdocs.openapi.gradle.schema.JsonFieldPath>,
124+
fields: List<com.epages.restdocs.openapi.generator.schema.JsonFieldPath>,
125125
description: String?
126126
) {
127127
val remainingSegments = fields[0].remainingSegments(traversedSegments)
128-
if (remainingSegments.isNotEmpty() && com.epages.restdocs.openapi.gradle.schema.JsonFieldPath.isArraySegment(remainingSegments[0])) {
128+
if (remainingSegments.isNotEmpty() && com.epages.restdocs.openapi.generator.schema.JsonFieldPath.isArraySegment(remainingSegments[0])) {
129129
traversedSegments.add(remainingSegments[0])
130130
builder.addPropertySchema(
131131
propertyName, ArraySchema.builder()
@@ -182,17 +182,17 @@ internal class JsonSchemaFromFieldDescriptorsGenerator {
182182
type: String,
183183
optional: Boolean,
184184
ignored: Boolean,
185-
attributes: com.epages.restdocs.openapi.gradle.Attributes,
185+
attributes: com.epages.restdocs.openapi.generator.Attributes,
186186
private val jsonSchemaPrimitiveTypes: Set<String> = setOf(jsonSchemaPrimitiveTypeFromDescriptorType(type))
187-
) : com.epages.restdocs.openapi.gradle.FieldDescriptor(path, description, type, optional, ignored, attributes) {
187+
) : com.epages.restdocs.openapi.generator.FieldDescriptor(path, description, type, optional, ignored, attributes) {
188188

189189
fun jsonSchemaType(): Schema {
190190
val schemaBuilders = jsonSchemaPrimitiveTypes.map { typeToSchema(it) }
191191
return if (schemaBuilders.size == 1) schemaBuilders.first().description(description).build()
192192
else CombinedSchema.oneOf(schemaBuilders.map { it.build() }).description(description).build()
193193
}
194194

195-
fun merge(fieldDescriptor: com.epages.restdocs.openapi.gradle.FieldDescriptor): FieldDescriptorWithSchemaType {
195+
fun merge(fieldDescriptor: com.epages.restdocs.openapi.generator.FieldDescriptor): FieldDescriptorWithSchemaType {
196196
if (this.path != fieldDescriptor.path)
197197
throw IllegalArgumentException("path of fieldDescriptor is not equal to ${this.path}")
198198

@@ -226,7 +226,7 @@ internal class JsonSchemaFromFieldDescriptorsGenerator {
226226
this.type == f.type)
227227

228228
companion object {
229-
fun fromFieldDescriptor(fieldDescriptor: com.epages.restdocs.openapi.gradle.FieldDescriptor) =
229+
fun fromFieldDescriptor(fieldDescriptor: com.epages.restdocs.openapi.generator.FieldDescriptor) =
230230
FieldDescriptorWithSchemaType(
231231
path = fieldDescriptor.path,
232232
description = fieldDescriptor.description,
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
package com.epages.restdocs.openapi.gradle
1+
package com.epages.restdocs.openapi.generator
22

3-
import com.epages.restdocs.openapi.gradle.SecurityType.OAUTH2
3+
import com.epages.restdocs.openapi.generator.SecurityType.OAUTH2
44
import io.swagger.models.Model
55
import io.swagger.models.Path
66
import io.swagger.models.Response
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
package com.epages.restdocs.openapi.gradle.schema
1+
package com.epages.restdocs.openapi.generator.schema
22

3-
import com.epages.restdocs.openapi.gradle.Attributes
4-
import com.epages.restdocs.openapi.gradle.schema.JsonFieldPath.Companion.compile
3+
import com.epages.restdocs.openapi.generator.schema.JsonFieldPath.Companion.compile
54
import com.google.common.collect.ImmutableList
65
import org.assertj.core.api.BDDAssertions.then
76
import org.junit.jupiter.api.Test
@@ -12,8 +11,8 @@ class JsonFieldPathTest {
1211
@Test
1312
fun should_get_remaining_segments() {
1413
with(compile(
15-
com.epages.restdocs.openapi.gradle.schema.JsonSchemaFromFieldDescriptorsGenerator.FieldDescriptorWithSchemaType("a.b.c", "", "", false, false,
16-
com.epages.restdocs.openapi.gradle.Attributes()
14+
com.epages.restdocs.openapi.generator.schema.JsonSchemaFromFieldDescriptorsGenerator.FieldDescriptorWithSchemaType("a.b.c", "", "", false, false,
15+
com.epages.restdocs.openapi.generator.Attributes()
1716
))) {
1817
then(remainingSegments(ImmutableList.of("a"))).contains("b", "c")
1918
then(remainingSegments(ImmutableList.of("a", "b"))).contains("c")

0 commit comments

Comments
 (0)