Polishing.

Add since tags. Reformat code. Switch to Collection-typed properties as Iterable is often used in domain models without being an actual mapped collection.

See #3010
Original pull request: #3241
This commit is contained in:
Mark Paluch
2025-02-10 14:36:33 +01:00
parent 11bdb9a0a9
commit c1cd613488
2 changed files with 33 additions and 33 deletions

View File

@@ -34,9 +34,10 @@ private class KPropertyPath<T, U>(
/**
* Abstraction of a property path that consists of parent [KProperty],
* and child property [KProperty], where parent [parent] has an [Iterable]
* of children, so it represents 1-M mapping, not 1-1, like [KPropertyPath]
* of children, so it represents 1-M mapping.
*
* @author Mikhail Polivakha
* @since 3.5
*/
internal class KIterablePropertyPath<T, U>(
val parent: KProperty<Iterable<U?>?>,
@@ -52,8 +53,8 @@ internal fun asString(property: KProperty<*>): String {
return when (property) {
is KPropertyPath<*, *> ->
"${asString(property.parent)}.${property.child.name}"
is KIterablePropertyPath<*, *> ->
"${asString(property.parent)}.${property.child.name}"
is KIterablePropertyPath<*, *> ->
"${asString(property.parent)}.${property.child.name}"
else -> property.name
}
}
@@ -81,21 +82,15 @@ operator fun <T, U> KProperty<T?>.div(other: KProperty1<T, U>): KProperty<U> =
* Note, that this function is different from [div] above in the
* way that it represents a division operator overloading for
* child references, where parent to child reference relation is 1-M, not 1-1.
* It implies that parent has an [Iterable] or any liner [Collection] of children.
* It implies that parent defines a [Collection] of children.
**
* For example, referring to the field "addresses.street":
* For example, referring to the field "books.title":
* ```
* User::addresses / Author::street contains "Austin"
* ```
*
* And the entities may look like this:
* ```
* class User(val addresses: List<Address>)
*
* class Address(val street: String)
* Author::books / Book::title contains "Bartleby"
* ```
* @author Mikhail Polivakha
* @since 3.5
*/
@JvmName("divIterable")
operator fun <T, U> KProperty<Iterable<T?>?>.div(other: KProperty1<T, U>): KProperty<U> =
operator fun <T, U> KProperty<Collection<T?>?>.div(other: KProperty1<T, U>): KProperty<U> =
KIterablePropertyPath(this, other)

View File

@@ -44,12 +44,20 @@ class KPropertyPathTests {
assertThat(property).isEqualTo("author.name")
}
@Test // DATACMNS-3010
@Test // GH-3010
fun `Convert from Iterable nested KProperty to field name`() {
val property = (User::addresses / Address::street).toDotPath()
val property = (Author::books / Book::title).toDotPath()
assertThat(property).isEqualTo("addresses.street")
assertThat(property).isEqualTo("books.title")
}
@Test // GH-3010
fun `Convert from Iterable nested Iterable Property to field name`() {
val property = (Author::books / Book::author / Author::name).toDotPath()
assertThat(property).isEqualTo("books.author.name")
}
@Test // DATACMNS-1835
@@ -73,6 +81,18 @@ class KPropertyPathTests {
assertThat(property).isEqualTo("entity.book.author.name")
}
@Test // DATACMNS-1835
fun `Convert triple nested KProperty to property path using toDotPath`() {
class Entity(val book: Book)
class AnotherEntity(val entity: Entity)
val property =
(AnotherEntity::entity / Entity::book / Book::author / Author::name).toDotPath()
assertThat(property).isEqualTo("entity.book.author.name")
}
@Test // DATACMNS-1835
fun `Convert simple KProperty to property path using toDotPath`() {
@@ -91,18 +111,6 @@ class KPropertyPathTests {
assertThat(property).isEqualTo("author.name")
}
@Test // DATACMNS-1835
fun `Convert triple nested KProperty to property path using toDotPath`() {
class Entity(val book: Book)
class AnotherEntity(val entity: Entity)
val property =
(AnotherEntity::entity / Entity::book / Book::author / Author::name).toDotPath()
assertThat(property).isEqualTo("entity.book.author.name")
}
@Test // DATACMNS-1835
fun `Convert nullable KProperty to field name`() {
@@ -114,9 +122,6 @@ class KPropertyPathTests {
}
class Book(val title: String, val author: Author)
class Author(val name: String)
class Author(val name: String, val books: List<Book>)
class User(val addresses: List<Address>)
class Address(val street: String)
}