Skip to content

Commit

Permalink
Make Kotlin-only functions top-level
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-yevsyukov committed Nov 3, 2023
1 parent 5c8c4b3 commit 85213a4
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

@file:JvmName("Stringify")

package io.spine.string

import com.google.common.escape.Escaper
Expand All @@ -34,9 +37,59 @@ import java.lang.reflect.Type
import kotlin.reflect.KClass

/**
* Utility class for working with `Stringifier`s.
* Obtains a string representation of this object using a [Stringifier] for the object type.
*
* @see Stringifiers.toString
*/
public inline fun <reified T : Any> T.stringify(): String =
Stringifiers.toString(this, T::class.java)

/**
* Same as [Stringifiers.fromString] for brevity in Kotlin code.
*/
public inline fun <reified T : Any> fromString(str: String): T =
Stringifiers.fromString(str, T::class.java)

/**
* Same as [Stringifier.fromString] accepting [KClass] instead of [Class].
*/
public fun <T : Any> fromString(str: String, cls: KClass<T>): T =
Stringifiers.fromString(str, cls.java)

/**
* Same as [Stringifiers.newForListOf] for brevity in Kotlin code.
*/
@Suppress("TooManyFunctions") // need to gather all of them here for easier usage.
public inline fun <reified T : Any> listStringifier(): Stringifier<List<T>> =
Stringifiers.newForListOf(T::class.java)

/**
* Same as [Stringifiers.newForListOf] for brevity in Kotlin code.
*/
public inline fun <reified T: Any> listStringifier(delimiter: Char): Stringifier<List<T>> =
Stringifiers.newForListOf(T::class.java, delimiter)

/**
* Same as [Stringifiers.newForMapOf] for brevity in Kotlin code.
*/
public inline fun <reified K : Any, reified V : Any> mapStringifier(): Stringifier<Map<K, V>> =
Stringifiers.newForMapOf(K::class.java, V::class.java)

/**
* Same as [Stringifiers.newForMapOf] for brevity in Kotlin code.
*/
public inline fun <reified K : Any, reified V : Any> mapStringifier(
delimiter: Char
): Stringifier<Map<K, V>> = Stringifiers.newForMapOf(K::class.java, V::class.java, delimiter)

/**
* Utility object for working with `Stringifier`s.
*
* **API Note**: This object is Kotlin port of the `Stringifiers` class from Java.
* It is kept as an object, rather than a group of top-level functions, to preserve backward
* compatibility with the existing Java code. It is expected that it will be gradually
* migrated to top-level functions with an appropriate deprecation cycle.
*/
@Suppress("TooManyFunctions") // Need to gather all of them here for easier usage.
public object Stringifiers {

/**
Expand All @@ -59,6 +112,7 @@ public object Stringifiers {
*
* The same as [toString] but with the ability for static import in Java.
*/
@JvmStatic
public fun <T : Any> stringify(obj: T): String = toString(obj)

/**
Expand Down Expand Up @@ -102,18 +156,6 @@ public object Stringifiers {
return result!!
}

/**
* Same as [fromString] accepting [KClass] instead of [Class].
*/
public fun <T : Any> fromString(str: String, cls: KClass<T>): T =
fromString(str, cls.java)

/**
* Same as [fromString] for brevity in Kotlin code.
*/
public inline fun <reified T : Any> fromString(str: String): T =
fromString(str, T::class.java)

/**
* Obtains `Stringifier` for the map with default delimiter for the passed map elements.
*
Expand All @@ -134,12 +176,6 @@ public object Stringifiers {
): Stringifier<Map<K, V>> = MapStringifier(keyClass, valueClass)


/**
* Same as [newForMapOf] for brevity in Kotlin code.
*/
public inline fun <reified K : Any, reified V : Any> newForMapOf(): Stringifier<Map<K, V>> =
newForMapOf(K::class.java, V::class.java)

/**
* Obtains `Stringifier` for the map with custom delimiter for the passed map elements.
*
Expand All @@ -161,13 +197,6 @@ public object Stringifiers {
delimiter: Char
): Stringifier<Map<K, V>> = MapStringifier(keyClass, valueClass, delimiter)

/**
* Same as [newForMapOf] for brevity in Kotlin code.
*/
public inline fun <reified K : Any, reified V : Any> newForMapOf(
delimiter: Char
): Stringifier<Map<K, V>> = newForMapOf(K::class.java, V::class.java, delimiter)

/**
* Obtains `Stringifier` for `Boolean` values.
*/
Expand Down Expand Up @@ -225,12 +254,6 @@ public object Stringifiers {
public fun <T : Any> newForListOf(elementClass: Class<T>): Stringifier<List<T>> =
ListStringifier(elementClass)

/**
* Same as [newForListOf] for brevity in Kotlin code.
*/
public inline fun <reified T : Any> newForListOf(): Stringifier<List<T>> =
newForListOf(T::class.java)

/**
* Obtains `Stringifier` for a list with the custom delimiter for the passed list elements.
*
Expand All @@ -247,12 +270,6 @@ public object Stringifiers {
delimiter: Char
): Stringifier<List<T>> = ListStringifier(elementClass, delimiter)

/**
* Same as [newForListOf] for brevity in Kotlin code.
*/
public inline fun <reified T: Any> newForListOf(delimiter: Char): Stringifier<List<T>> =
newForListOf(T::class.java, delimiter)

/**
* Obtains a `Stringifier` for the passed `enum` class.
*
Expand Down
16 changes: 8 additions & 8 deletions src/main/kotlin/io/spine/string/Strings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@

package io.spine.string

/**
* This file contains extension functions for obtaining <em>standard</em> string
* representation of various objects. For string representations using [Stringifier],
* please see [io.spine.string.Stringifiers].
*/
@Suppress("unused")
private const val ABOUT = ""

/**
* Joins these strings into a `CamelCase` string.
*
Expand Down Expand Up @@ -102,14 +110,6 @@ public fun String.ti(): String = trimIndent().fixLineEndings()
public fun String.pi(indent: String = Indent.defaultJavaIndent.value): String =
prependIndent(indent).fixLineEndings()

/**
* Obtains a string representation of this object using a [Stringifier] for the object type.
*
* @see Stringifiers.toString
*/
public inline fun <reified T : Any> T.stringify(): String =
Stringifiers.toString(this, T::class.java)

/**
* Joins the elements of this `Iterable` into a single string having each item on a separate line.
*/
Expand Down
44 changes: 44 additions & 0 deletions src/test/java/io/spine/string/StringifyJavaSpec.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2023, TeamDev. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and/or binary forms, with or without
* modification, must retain the above copyright notice and the following
* disclaimer.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package io.spine.string;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static com.google.common.truth.Truth.assertThat;
import static io.spine.string.Stringifiers.stringify;

@DisplayName("`Stringify` should")
class StringifyJavaSpec {

@Test
@DisplayName("provide `stringify()` method")
void provideStringifyMethod() {
var value = "foo-bar";
assertThat(stringify(value)).isEqualTo(value);
}
}
9 changes: 4 additions & 5 deletions src/test/kotlin/io/spine/string/StringifiersSpec.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldContain
import io.spine.base.Identifier
import io.spine.base.Time
import io.spine.string.Stringifiers.fromString
import io.spine.string.Stringifiers.stringify
import io.spine.test.string.STask
import io.spine.test.string.STaskId
Expand All @@ -60,7 +59,7 @@ internal class StringifiersSpec : UtilityClassTest<Stringifiers>(Stringifiers::c

@Nested
@DisplayName("stringify")
internal inner class Stringify {
internal inner class StringifyKt {

@Test
fun boolean() = checkStringifies(false, "false")
Expand Down Expand Up @@ -122,7 +121,7 @@ internal class StringifiersSpec : UtilityClassTest<Stringifiers>(Stringifiers::c
@Test
fun List() {
val stamps: List<Timestamp> = createList()
val stringifier = Stringifiers.newForListOf<Timestamp>(DELIMITER)
val stringifier = listStringifier<Timestamp>(DELIMITER)
val out = stringifier.toString(stamps)

out shouldContain DELIMITER.toString()
Expand All @@ -136,7 +135,7 @@ internal class StringifiersSpec : UtilityClassTest<Stringifiers>(Stringifiers::c
@Test
fun Map() {
val stamps = createMap()
val stringifier = Stringifiers.newForMapOf<Long, Timestamp>(DELIMITER)
val stringifier = mapStringifier<Long, Timestamp>(DELIMITER)
val out = stringifier.toString(stamps)

out shouldContain DELIMITER.toString()
Expand Down Expand Up @@ -187,7 +186,7 @@ internal class StringifiersSpec : UtilityClassTest<Stringifiers>(Stringifiers::c
@Test
fun List() {
val numbers: List<Int> = ImmutableList.of(100, 200, -300)
val stringifier = Stringifiers.newForListOf<Int>()
val stringifier = listStringifier<Int>()
val numString = stringifier.toString(numbers)

val parsed = stringifier.fromString(numString)
Expand Down

0 comments on commit 85213a4

Please sign in to comment.