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

com.gw2tb.apigen.model.Name.kt Maven / Gradle / Ivy

/*
 * Copyright (c) 2019-2024 Leon Linhart
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.gw2tb.apigen.model

/**
 * An abstraction for names that provides several functions to convert a name to
 * a [String] representation in a desired casing.
 *
 * @since   0.7.0
 */
@Suppress("DataClassPrivateConstructor")
public data class Name private constructor(
    private val camelCase: String,
    private val snakeCase: String,
    private val titleCase: String
) {

    public constructor(vararg segments: String): this(
        camelCase = segments.first().lowercase() + segments.drop(1).joinToString(separator = ""),
        snakeCase = segments.joinToString(separator = "_") { it.lowercase() },
        titleCase = segments.joinToString(separator = "")
    )

    internal companion object {

        @Suppress("NAME_SHADOWING")
        fun derive(camelCase: String? = null, snakeCase: String? = null, titleCase: String? = null): Name {
            fun String.firstToLowerCase(): String =
                "${toCharArray()[0].lowercaseChar()}${substring(1)}"

            fun String.firstToUpperCase(): String =
                "${toCharArray()[0].uppercaseChar()}${substring(1)}"

            fun String.splitCasing(): List = buildList {
                var remaining = this@splitCasing

                while (remaining.isNotEmpty()) {
                    val segment = buildString {
                        if (remaining.first() == '/') {
                            append("/")
                            remaining = remaining.drop(1)
                        }

                        if (remaining.first().isUpperCase()) {
                            append(remaining.first())
                            remaining = remaining.drop(1)
                        }

                        val buf = remaining.takeWhile { it != '/' && !it.isUpperCase() }
                        remaining = remaining.drop(buf.length)
                        append(buf)
                    }

                    if (segment.isNotEmpty()) {
                        add(segment)
                    }
                }
            }

            fun List.joinToSnakeCase(): String = buildString {
                append([email protected]().lowercase())

                [email protected](1).forEach { segment ->
                    if (!segment.startsWith("/")) append("_")
                    append(segment.lowercase())
                }
            }

            val snakeCase = snakeCase ?: (camelCase ?: titleCase)?.splitCasing()?.joinToSnakeCase() ?: error("At least one must be non null")
            val camelCase = camelCase ?: titleCase?.firstToLowerCase() ?: snakeCase.split("_").joinToString(separator = "") { it.firstToUpperCase() }
            val titleCase = titleCase ?: camelCase.firstToUpperCase()

            return Name(camelCase = camelCase, snakeCase = snakeCase, titleCase = titleCase)
        }

        fun deriveFromTitleCase(value: String): Name =
            derive(titleCase = value)

    }

    init {
        require(camelCase.isNotBlank()) { "Name[camelCase] must not be blank for $this" }
        require(snakeCase.isNotBlank()) { "Name[snakeCase] must not be blank for $this" }
        require(titleCase.isNotBlank()) { "Name[titleCase] must not be blank for $this" }
    }

    /**
     * Returns a [String] representation of this name in `camelCase`.
     *
     * @since   0.7.0
     */
    public fun toCamelCase(): String = camelCase

    /**
     * Returns a [String] representation of this name in `snake_case`.
     *
     * @since   0.7.0
     */
    public fun toSnakeCase(): String = snakeCase

    /**
     * Returns a [String] representation of this name in `TitleCase`.
     *
     * @since   0.7.0
     */
    public fun toTitleCase(): String = titleCase

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy