mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2024-11-18 06:13:49 +00:00
215 lines
6.9 KiB
Kotlin
215 lines
6.9 KiB
Kotlin
import io.ktor.client.HttpClient
|
|
import io.ktor.client.request.get
|
|
import kotlinx.serialization.SerialName
|
|
import kotlinx.serialization.Serializable
|
|
import kotlinx.serialization.builtins.ListSerializer
|
|
import kotlinx.serialization.json.Json
|
|
import java.io.File
|
|
import java.text.Normalizer
|
|
|
|
private val json = Json {
|
|
ignoreUnknownKeys = true
|
|
}
|
|
|
|
private const val baseClassName = "IetfLanguageCode"
|
|
private const val unknownBaseClassName = "Unknown$baseClassName"
|
|
private const val baseClassSerializerName = "IetfLanguageCodeSerializer"
|
|
private const val baseClassSerializerAnnotationName = "@Serializable(${baseClassSerializerName}::class)"
|
|
|
|
@Serializable
|
|
private data class LanguageCode(
|
|
@SerialName("alpha2")
|
|
val tag: String,
|
|
@SerialName("English")
|
|
val title: String
|
|
)
|
|
|
|
fun String.adaptAsTitle() = if (first().isDigit()) {
|
|
"L$this"
|
|
} else {
|
|
this
|
|
}
|
|
|
|
fun String.normalized() = Normalizer.normalize(this, Normalizer.Form.NFD).replace(Regex("[^\\p{ASCII}]"), "")
|
|
|
|
@Serializable
|
|
private data class LanguageCodeWithTag(
|
|
@SerialName("langType")
|
|
val tag: String,
|
|
@SerialName("lang")
|
|
val withSubtag: String
|
|
) {
|
|
val partWithoutTag: String
|
|
get() {
|
|
return withSubtag.substring(
|
|
withSubtag.indexOf("-") + 1, withSubtag.length
|
|
)
|
|
}
|
|
val middleTag
|
|
get() = if (partWithoutTag.contains("-")) {
|
|
partWithoutTag.substring(0, partWithoutTag.indexOf("-"))
|
|
} else {
|
|
null
|
|
}
|
|
val middleTagTitle
|
|
get() = middleTag ?.adaptAsTitle() ?: partWithoutTag.adaptAsTitle()
|
|
val subtag: String
|
|
get() = middleTag ?: partWithoutTag
|
|
val endTag
|
|
get() = if (partWithoutTag.contains("-")) {
|
|
partWithoutTag.substring(partWithoutTag.indexOf("-") + 1, partWithoutTag.length)
|
|
} else {
|
|
null
|
|
}
|
|
val endTagAsTitle
|
|
get() = endTag ?.adaptAsTitle()
|
|
}
|
|
|
|
data class Tag(
|
|
val title: String,
|
|
val tag: String,
|
|
val subtags: List<Tag>
|
|
)
|
|
|
|
private fun printLanguageCodeAndTags(
|
|
tag: Tag,
|
|
parent: Tag? = null,
|
|
indents: String = " "
|
|
): String = if (tag.subtags.isEmpty()) {
|
|
"""${indents}${baseClassSerializerAnnotationName}
|
|
${indents}object ${tag.title} : ${parent ?.title ?: baseClassName}() { override val code: String = "${tag.tag}" }"""
|
|
} else {
|
|
"""
|
|
${indents}${baseClassSerializerAnnotationName}
|
|
${indents}sealed class ${tag.title} : ${parent ?.title ?: baseClassName}() {
|
|
${indents} override val code: String = "${tag.tag}"
|
|
|
|
${tag.subtags.joinToString("\n") { printLanguageCodeAndTags(it, tag, "${indents} ") }}
|
|
|
|
${indents} ${baseClassSerializerAnnotationName}
|
|
${indents} companion object : ${tag.title}()
|
|
${indents}}
|
|
"""
|
|
}
|
|
|
|
fun buildKtFileContent(tags: List<Tag>): String = """
|
|
import kotlinx.serialization.Serializable
|
|
|
|
/**
|
|
* This class has been automatically generated using
|
|
* https://github.com/InsanusMokrassar/MicroUtils/tree/master/language_codes/generator . This generator uses
|
|
* https://datahub.io/core/language-codes/ files (base and tags) and create the whole hierarchy using it.
|
|
*/
|
|
${baseClassSerializerAnnotationName}
|
|
sealed class $baseClassName {
|
|
abstract val code: String
|
|
|
|
${tags.joinToString("\n") { printLanguageCodeAndTags(it, indents = " ") } }
|
|
|
|
$baseClassSerializerAnnotationName
|
|
data class $unknownBaseClassName (override val code: String) : $baseClassName()
|
|
|
|
override fun toString() = code
|
|
}
|
|
""".trimIndent()
|
|
|
|
fun createStringConverterCode(tags: List<Tag>): String {
|
|
fun createDeserializeVariantForTag(
|
|
tag: Tag,
|
|
pretitle: String = baseClassName,
|
|
indents: String = " "
|
|
): String {
|
|
val currentTitle = "$pretitle.${tag.title}"
|
|
return """${indents}$currentTitle.code -> $currentTitle${if (tag.subtags.isNotEmpty()) tag.subtags.joinToString("\n", "\n") { createDeserializeVariantForTag(it, currentTitle, indents) } else ""}"""
|
|
}
|
|
|
|
return """fun String.as$baseClassName(): $baseClassName {
|
|
return when (this) {
|
|
${tags.joinToString("\n") { createDeserializeVariantForTag(it) }}
|
|
else -> $baseClassName.${unknownBaseClassName}(this)
|
|
}
|
|
}
|
|
fun convertTo$baseClassName(code: String) = code.as$baseClassName()
|
|
fun $baseClassName(code: String) = code.as$baseClassName()
|
|
"""
|
|
}
|
|
|
|
fun createSerializerCode(tags: List<Tag>): String {
|
|
return """import kotlinx.serialization.KSerializer
|
|
import kotlinx.serialization.builtins.serializer
|
|
import kotlinx.serialization.encoding.Decoder
|
|
import kotlinx.serialization.encoding.Encoder
|
|
|
|
object $baseClassSerializerName : KSerializer<$baseClassName> {
|
|
override val descriptor = String.serializer().descriptor
|
|
|
|
override fun deserialize(decoder: Decoder): $baseClassName {
|
|
return $baseClassName(decoder.decodeString())
|
|
}
|
|
|
|
override fun serialize(encoder: Encoder, value: IetfLanguageCode) {
|
|
encoder.encodeString(value.code)
|
|
}
|
|
}
|
|
"""
|
|
}
|
|
|
|
suspend fun main(vararg args: String) {
|
|
val outputFolder = args.firstOrNull() ?.let { File(it) }
|
|
outputFolder ?.mkdirs()
|
|
val ietfLanguageCodesLink = "https://datahub.io/core/language-codes/r/language-codes.json"
|
|
val ietfLanguageCodesAdditionalTagsLink = "https://datahub.io/core/language-codes/r/ietf-language-tags.json"
|
|
|
|
val client = HttpClient()
|
|
|
|
val ietfLanguageCodes = json.decodeFromString(
|
|
ListSerializer(LanguageCode.serializer()),
|
|
client.get(ietfLanguageCodesLink)
|
|
).map {
|
|
it.copy(
|
|
title = it.title
|
|
.replace(Regex("[;,()-]"), "")
|
|
.split(" ")
|
|
.joinToString("") { "${it.first().uppercase()}${it.substring(1)}" }
|
|
)
|
|
}
|
|
val ietfLanguageCodesWithTagsMap = json.decodeFromString(
|
|
ListSerializer(LanguageCodeWithTag.serializer()),
|
|
client.get(ietfLanguageCodesAdditionalTagsLink)
|
|
).filter { it.withSubtag != it.tag }.groupBy { it.tag }
|
|
|
|
val tags = ietfLanguageCodes.map {
|
|
val unformattedSubtags = ietfLanguageCodesWithTagsMap[it.tag] ?: emptyList()
|
|
val threeLevelTags = unformattedSubtags.filter { it.endTag != null }.groupBy { it.middleTag }
|
|
val subtags = unformattedSubtags.mapNotNull {
|
|
if (it.endTag == null) {
|
|
val currentSubtags = (threeLevelTags[it.subtag] ?: emptyList()).map {
|
|
Tag(it.endTagAsTitle!!.normalized(), it.withSubtag, emptyList())
|
|
}
|
|
Tag(it.middleTagTitle.normalized(), it.withSubtag, currentSubtags)
|
|
} else {
|
|
null
|
|
}
|
|
}
|
|
Tag(it.title.normalized(), it.tag, subtags)
|
|
}
|
|
|
|
File(outputFolder, "LanguageCodes.kt").apply {
|
|
delete()
|
|
createNewFile()
|
|
writeText(buildKtFileContent(tags))
|
|
}
|
|
|
|
File(outputFolder, "StringToLanguageCodes.kt").apply {
|
|
delete()
|
|
createNewFile()
|
|
writeText(createStringConverterCode(tags))
|
|
}
|
|
|
|
File(outputFolder, "$baseClassSerializerName.kt").apply {
|
|
delete()
|
|
createNewFile()
|
|
writeText(createSerializerCode(tags))
|
|
}
|
|
}
|