All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ancientlightstudios.quarkus.kotlin.openapi.refactoring.SchemaNameRefactoring.kt Maven / Gradle / Ivy

There is a newer version: 0.4.14
Show newest version
package com.ancientlightstudios.quarkus.kotlin.openapi.refactoring

import com.ancientlightstudios.quarkus.kotlin.openapi.inspection.inspect
import com.ancientlightstudios.quarkus.kotlin.openapi.models.hints.NameSuggestionHint.nameSuggestion
import com.ancientlightstudios.quarkus.kotlin.openapi.models.transformable.TransformableSchema
import com.ancientlightstudios.quarkus.kotlin.openapi.models.transformable.components.ArrayItemsComponent
import com.ancientlightstudios.quarkus.kotlin.openapi.models.transformable.components.ObjectComponent
import com.ancientlightstudios.quarkus.kotlin.openapi.models.transformable.components.SomeOfComponent
import com.ancientlightstudios.quarkus.kotlin.openapi.utils.ProbableBug
import com.ancientlightstudios.quarkus.kotlin.openapi.utils.pop

class SchemaNameRefactoring : SpecRefactoring {

    override fun RefactoringContext.perform() {
        // first step: name every schema used directly by a request or response if no name is set yet
        spec.inspect {
            bundles {
                requests {
                    val requestPrefix = request.operationId
                    parameters {
                        assignName(
                            parameter.content.schema,
                            parameter.nameSuggestion,
                            "$requestPrefix ${parameter.name} parameter"
                        )
                    }

                    body {
                        assignName(body.content.schema, body.nameSuggestion, "$requestPrefix body")
                    }

                    responses {
                        val responsePrefix = "$requestPrefix ${response.responseCode}"
                        headers {
                            assignName(
                                header.content.schema,
                                header.nameSuggestion,
                                "$responsePrefix ${header.name} header"
                            )
                        }

                        body {
                            assignName(body.content.schema, body.nameSuggestion, "$responsePrefix response")
                        }
                    }
                }
            }
        }

        // second step: assign names to every schema used within other schema if no name is yet set
        // we start with already named schemas
        val definitionsWithNames = spec.schemas.filterNot { it.name.isBlank() }.toMutableSet()

        // helper function to avoid code duplication
        val assignAndSchedule: (TransformableSchema, fallback: String) -> Unit = { schema, name ->
            if (assignName(schema, null, name)) {
                // if a name was given to the schema, add it to the set to check its sub schemas too
                definitionsWithNames.add(schema)
            }
        }

        // we can ignore BaseDefinitionComponents here, because these schemas should already have a name based on the reference
        while (definitionsWithNames.isNotEmpty()) {
            definitionsWithNames.pop { current ->
                current.inspect {
                    val prefix = schema.name
                    components { assignAndSchedule(component.schema, "$prefix items") }
                    components {
                        component.properties.forEach {
                            assignAndSchedule(it.schema, "$prefix ${it.name}")
                        }
                    }
                    components {
                        component.schemas.forEachIndexed { index, schema ->
                            assignAndSchedule(schema.schema, "$prefix option ${index + 1}")
                        }
                    }
                }
            }
        }

        if (spec.schemas.any { it.name.isBlank() }) {
            ProbableBug("Could not assign names to some schemas")
        }
    }

    private fun assignName(schema: TransformableSchema, suggestion: String?, fallback: String): Boolean {
        if (schema.name.isNotBlank()) {
            // already a name assigned
            return false
        }

        schema.name = suggestion ?: fallback
        return true
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy