dev.fuelyour.vertxkuickstartcore.tools.SwaggerMerger.kt Maven / Gradle / Ivy
package dev.fuelyour.vertxkuickstartcore.tools
import io.swagger.v3.oas.models.Components
import io.swagger.v3.oas.models.OpenAPI
import io.swagger.v3.parser.OpenAPIV3Parser
import io.vertx.ext.web.api.contract.openapi3.impl.OpenApi3Utils
import org.apache.commons.collections4.ListUtils
import org.reflections.Reflections
import org.reflections.scanners.ResourcesScanner
/**
* Merge multiple swagger documents into one. This allows swagger documents to be broken down into manageable pieces,
* and merged back together for final documentation generation.
*/
object SwaggerMerger {
fun mergeAllInDirectory(path: String): OpenAPI? =
findSwaggerFilesInPath(path)
.map { loadSwagger("/$it") }
.fold(null as OpenAPI?) { s1, s2 ->
s1?.merge(s2) ?: s2
}
private fun findSwaggerFilesInPath(path: String): Set =
Reflections(path, ResourcesScanner())
.getResources { it?.endsWith(".yaml") ?: false }
private fun loadSwagger(filename: String): OpenAPI =
OpenAPIV3Parser()
.readLocation(filename, null, OpenApi3Utils.getParseOptions())
.openAPI
private fun OpenAPI.merge(new: OpenAPI): OpenAPI {
servers = combineLists(servers, new.servers)
security = combineLists(security, new.security)
tags = combineLists(tags, new.tags)
new.paths?.forEach { it -> paths.addPathItem(it.key, it.value) }
extensions = combineMaps(extensions, new.extensions)
components.merge(new.components)
if (info == null)
info = new.info
return this
}
private fun Components.merge(other: Components) {
schemas = combineMaps(schemas, other.schemas)
responses = combineMaps(responses, other.responses)
parameters = combineMaps(parameters, other.parameters)
examples = combineMaps(examples, other.examples)
requestBodies = combineMaps(requestBodies, other.requestBodies)
headers = combineMaps(headers, other.headers)
securitySchemes = combineMaps(securitySchemes, other.securitySchemes)
links = combineMaps(links, other.links)
callbacks = combineMaps(callbacks, other.callbacks)
extensions = combineMaps(extensions, other.extensions)
}
private fun combineLists(list1: List?, list2: List?): List? {
val combined = ListUtils.union(
list1 ?: listOf(),
list2 ?: listOf()
)
return if (combined.isEmpty()) null else combined
}
private fun combineMaps(
map1: MutableMap?,
map2: MutableMap?
): MutableMap? {
return when {
map1 == null -> map2
map2 == null -> map1
else -> {
val combined = linkedMapOf()
combined.putAll(map1)
combined.putAll(map2)
combined
}
}
}
}