diff --git a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/path/impl/JpqlEntityProperty.kt b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/path/impl/JpqlEntityProperty.kt index 0297c5a75..f7ce0e330 100644 --- a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/path/impl/JpqlEntityProperty.kt +++ b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/path/impl/JpqlEntityProperty.kt @@ -3,10 +3,10 @@ package com.linecorp.kotlinjdsl.querymodel.jpql.path.impl import com.linecorp.kotlinjdsl.Internal import com.linecorp.kotlinjdsl.querymodel.jpql.entity.Entity import com.linecorp.kotlinjdsl.querymodel.jpql.path.Path -import kotlin.reflect.KProperty1 +import kotlin.reflect.KCallable @Internal data class JpqlEntityProperty internal constructor( - val entity: Entity<*>, - val property: KProperty1, + val entity: Entity, + val property: KCallable, ) : Path diff --git a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/path/impl/JpqlPathProperty.kt b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/path/impl/JpqlPathProperty.kt index 1adb203d5..556efd5cf 100644 --- a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/path/impl/JpqlPathProperty.kt +++ b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/path/impl/JpqlPathProperty.kt @@ -2,10 +2,10 @@ package com.linecorp.kotlinjdsl.querymodel.jpql.path.impl import com.linecorp.kotlinjdsl.Internal import com.linecorp.kotlinjdsl.querymodel.jpql.path.Path -import kotlin.reflect.KProperty1 +import kotlin.reflect.KCallable @Internal data class JpqlPathProperty internal constructor( val path: Path, - val property: KProperty1, + val property: KCallable, ) : Path diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/JpqlRenderContext.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/JpqlRenderContext.kt index 47380d5b0..422be8953 100644 --- a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/JpqlRenderContext.kt +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/JpqlRenderContext.kt @@ -9,6 +9,7 @@ import com.linecorp.kotlinjdsl.render.jpql.introspector.JpqlIntrospectorModifier import com.linecorp.kotlinjdsl.render.jpql.introspector.JpqlRenderIntrospector import com.linecorp.kotlinjdsl.render.jpql.introspector.impl.JakartaJpqlIntrospector import com.linecorp.kotlinjdsl.render.jpql.introspector.impl.JavaxJpqlIntrospector +import com.linecorp.kotlinjdsl.render.jpql.introspector.impl.KotlinStyleJpqlPropertyIntrospector import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlRenderSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlSerializerModifier @@ -246,6 +247,8 @@ private class DefaultModule : JpqlRenderModule { context.appendIntrospector(JakartaJpqlIntrospector()) } + context.appendIntrospector(KotlinStyleJpqlPropertyIntrospector()) + context.addAllSerializer( JpqlAliasedExpressionSerializer(), JpqlAndSerializer(), diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/CombinedJpqlIntrospector.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/CombinedJpqlIntrospector.kt index b69a43a4a..88b1f5965 100644 --- a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/CombinedJpqlIntrospector.kt +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/CombinedJpqlIntrospector.kt @@ -1,6 +1,7 @@ package com.linecorp.kotlinjdsl.render.jpql.introspector import com.linecorp.kotlinjdsl.SinceJdsl +import kotlin.reflect.KCallable import kotlin.reflect.KClass /** @@ -20,4 +21,14 @@ class CombinedJpqlIntrospector( override fun introspect(type: KClass<*>): JpqlEntityDescription? { return primary.introspect(type) ?: secondary.introspect(type) } + + /** + * Get the entity information by introspecting KCallable. + * + * If the primary introspector introspects this KCallable, it returns the result of the primary introspector. + * Otherwise, it returns the result of the secondary introspector. + */ + override fun introspect(property: KCallable<*>): JpqlPropertyDescription? { + return primary.introspect(property) ?: secondary.introspect(property) + } } diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlEntityIntrospector.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlEntityIntrospector.kt new file mode 100644 index 000000000..30024b3b4 --- /dev/null +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlEntityIntrospector.kt @@ -0,0 +1,12 @@ +package com.linecorp.kotlinjdsl.render.jpql.introspector + +import com.linecorp.kotlinjdsl.SinceJdsl +import kotlin.reflect.KCallable + +/** + * Abstract class to get the entity information by introspecting KClass. + */ +@SinceJdsl("3.1.0") +abstract class JpqlEntityIntrospector : JpqlIntrospector { + override fun introspect(property: KCallable<*>): JpqlPropertyDescription? = null +} diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlIntrospector.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlIntrospector.kt index 564800d74..c4a5ae032 100644 --- a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlIntrospector.kt +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlIntrospector.kt @@ -1,6 +1,7 @@ package com.linecorp.kotlinjdsl.render.jpql.introspector import com.linecorp.kotlinjdsl.SinceJdsl +import kotlin.reflect.KCallable import kotlin.reflect.KClass /** @@ -14,4 +15,11 @@ interface JpqlIntrospector { */ @SinceJdsl("3.0.0") fun introspect(type: KClass<*>): JpqlEntityDescription? + + /** + * Introspects the KCallable to get the entity information. + * If it cannot introspect this KCallable, it returns null. + */ + @SinceJdsl("3.1.0") + fun introspect(property: KCallable<*>): JpqlPropertyDescription? } diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlPropertyDescription.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlPropertyDescription.kt new file mode 100644 index 000000000..917d73ab9 --- /dev/null +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlPropertyDescription.kt @@ -0,0 +1,12 @@ +package com.linecorp.kotlinjdsl.render.jpql.introspector + +import com.linecorp.kotlinjdsl.SinceJdsl + +/** + * Interface to represent the property information. + */ +@SinceJdsl("3.1.0") +interface JpqlPropertyDescription { + @SinceJdsl("3.1.0") + val name: String +} diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlPropertyIntrospector.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlPropertyIntrospector.kt new file mode 100644 index 000000000..99347270e --- /dev/null +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlPropertyIntrospector.kt @@ -0,0 +1,12 @@ +package com.linecorp.kotlinjdsl.render.jpql.introspector + +import com.linecorp.kotlinjdsl.SinceJdsl +import kotlin.reflect.KClass + +/** + * Abstract class to get the entity information by introspecting KCallable. + */ +@SinceJdsl("3.1.0") +abstract class JpqlPropertyIntrospector : JpqlIntrospector { + override fun introspect(type: KClass<*>): JpqlEntityDescription? = null +} diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlRenderIntrospector.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlRenderIntrospector.kt index 0c2c412f2..c012aade9 100644 --- a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlRenderIntrospector.kt +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/JpqlRenderIntrospector.kt @@ -4,6 +4,7 @@ import com.linecorp.kotlinjdsl.SinceJdsl import com.linecorp.kotlinjdsl.render.AbstractRenderContextElement import com.linecorp.kotlinjdsl.render.RenderContext import java.util.concurrent.ConcurrentHashMap +import kotlin.reflect.KCallable import kotlin.reflect.KClass /** @@ -15,7 +16,8 @@ class JpqlRenderIntrospector( ) : AbstractRenderContextElement(Key) { companion object Key : RenderContext.Key - private val tableLookupCache: MutableMap, JpqlEntityDescription> = ConcurrentHashMap() + private val entityLookupCache: MutableMap, JpqlEntityDescription> = ConcurrentHashMap() + private val propertyLookupCache: MutableMap, JpqlPropertyDescription> = ConcurrentHashMap() /** * Creates a new introspector by combining this introspector and the introspector. @@ -38,8 +40,22 @@ class JpqlRenderIntrospector( return getCachedDescription(clazz) } + /** + * Introspects the KCallable to get the property information. + */ + @SinceJdsl("3.1.0") + fun introspect(property: KCallable<*>): JpqlPropertyDescription { + return getCachedDescription(property) + } + private fun getCachedDescription(clazz: KClass<*>): JpqlEntityDescription { - return tableLookupCache.computeIfAbsent(clazz) { + return entityLookupCache.computeIfAbsent(clazz) { + getDescription(it) + } + } + + private fun getCachedDescription(property: KCallable<*>): JpqlPropertyDescription { + return propertyLookupCache.computeIfAbsent(property) { getDescription(it) } } @@ -48,4 +64,9 @@ class JpqlRenderIntrospector( return introspector.introspect(clazz) ?: throw IllegalStateException("There is no description for ${clazz.java.name}") } + + private fun getDescription(property: KCallable<*>): JpqlPropertyDescription { + return introspector.introspect(property) + ?: throw IllegalStateException("There is no description for ${property.name}") + } } diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/JakartaJpqlIntrospector.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/JakartaJpqlIntrospector.kt index eb6f67d27..b7f75b54b 100644 --- a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/JakartaJpqlIntrospector.kt +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/JakartaJpqlIntrospector.kt @@ -2,7 +2,7 @@ package com.linecorp.kotlinjdsl.render.jpql.introspector.impl import com.linecorp.kotlinjdsl.Internal import com.linecorp.kotlinjdsl.render.jpql.introspector.JpqlEntityDescription -import com.linecorp.kotlinjdsl.render.jpql.introspector.JpqlIntrospector +import com.linecorp.kotlinjdsl.render.jpql.introspector.JpqlEntityIntrospector import kotlin.reflect.KClass import kotlin.reflect.full.findAnnotations @@ -10,7 +10,7 @@ import kotlin.reflect.full.findAnnotations * Introspector that introspects KClass using [jakarta.persistence.Entity]. */ @Internal -class JakartaJpqlIntrospector : JpqlIntrospector { +class JakartaJpqlIntrospector : JpqlEntityIntrospector() { override fun introspect(type: KClass<*>): JpqlEntityDescription? { val entity = type.findAnnotations(jakarta.persistence.Entity::class).firstOrNull() diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/JavaxJpqlIntrospector.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/JavaxJpqlIntrospector.kt index a60bf18c6..3effe861d 100644 --- a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/JavaxJpqlIntrospector.kt +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/JavaxJpqlIntrospector.kt @@ -2,7 +2,7 @@ package com.linecorp.kotlinjdsl.render.jpql.introspector.impl import com.linecorp.kotlinjdsl.Internal import com.linecorp.kotlinjdsl.render.jpql.introspector.JpqlEntityDescription -import com.linecorp.kotlinjdsl.render.jpql.introspector.JpqlIntrospector +import com.linecorp.kotlinjdsl.render.jpql.introspector.JpqlEntityIntrospector import kotlin.reflect.KClass import kotlin.reflect.full.findAnnotations @@ -10,7 +10,7 @@ import kotlin.reflect.full.findAnnotations * Introspector that introspects KClass using [javax.persistence.Entity]. */ @Internal -class JavaxJpqlIntrospector : JpqlIntrospector { +class JavaxJpqlIntrospector : JpqlEntityIntrospector() { override fun introspect(type: KClass<*>): JpqlEntityDescription? { val entity = type.findAnnotations(javax.persistence.Entity::class).firstOrNull() diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/KotlinStyleJpqlPropertyIntrospector.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/KotlinStyleJpqlPropertyIntrospector.kt new file mode 100644 index 000000000..fc60d4db0 --- /dev/null +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/KotlinStyleJpqlPropertyIntrospector.kt @@ -0,0 +1,33 @@ +package com.linecorp.kotlinjdsl.render.jpql.introspector.impl + +import com.linecorp.kotlinjdsl.Internal +import com.linecorp.kotlinjdsl.render.jpql.introspector.JpqlPropertyDescription +import com.linecorp.kotlinjdsl.render.jpql.introspector.JpqlPropertyIntrospector +import kotlin.reflect.KCallable +import kotlin.reflect.KFunction1 +import kotlin.reflect.KProperty1 + +/** + * Introspector that introspects a property name in KCallable using Kotlin style. + */ +@Internal +class KotlinStyleJpqlPropertyIntrospector : JpqlPropertyIntrospector() { + override fun introspect(property: KCallable<*>): JpqlPropertyDescription? { + return when (property) { + is KProperty1<*, *> -> KotlinStyleProperty(property.name) + is KFunction1<*, *> -> KotlinStyleProperty(resolvePropertyName(property)) + else -> null + } + } + + private fun resolvePropertyName(getter: KFunction1<*, *>): String = + if (getter.name.startsWith("is")) { + getter.name + } else { + getter.name.removePrefix("get").replaceFirstChar { it.lowercase() } + } +} + +private data class KotlinStyleProperty( + override val name: String, +) : JpqlPropertyDescription diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlEntityPropertySerializer.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlEntityPropertySerializer.kt index d3d89c177..87f599c37 100644 --- a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlEntityPropertySerializer.kt +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlEntityPropertySerializer.kt @@ -3,6 +3,7 @@ package com.linecorp.kotlinjdsl.render.jpql.serializer.impl import com.linecorp.kotlinjdsl.Internal import com.linecorp.kotlinjdsl.querymodel.jpql.path.impl.JpqlEntityProperty import com.linecorp.kotlinjdsl.render.RenderContext +import com.linecorp.kotlinjdsl.render.jpql.introspector.JpqlRenderIntrospector import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlSerializer import com.linecorp.kotlinjdsl.render.jpql.writer.JpqlWriter import kotlin.reflect.KClass @@ -14,8 +15,11 @@ class JpqlEntityPropertySerializer : JpqlSerializer> { } override fun serialize(part: JpqlEntityProperty<*, *>, writer: JpqlWriter, context: RenderContext) { + val introspector = context.getValue(JpqlRenderIntrospector) + val property = introspector.introspect(part.property) + writer.write(part.entity.alias) writer.write(".") - writer.write(part.property.name) + writer.write(property.name) } } diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPathPropertySerializer.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPathPropertySerializer.kt index c2939a3b7..954376b2e 100644 --- a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPathPropertySerializer.kt +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPathPropertySerializer.kt @@ -3,6 +3,7 @@ package com.linecorp.kotlinjdsl.render.jpql.serializer.impl import com.linecorp.kotlinjdsl.Internal import com.linecorp.kotlinjdsl.querymodel.jpql.path.impl.JpqlPathProperty import com.linecorp.kotlinjdsl.render.RenderContext +import com.linecorp.kotlinjdsl.render.jpql.introspector.JpqlRenderIntrospector import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlRenderSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlSerializer import com.linecorp.kotlinjdsl.render.jpql.writer.JpqlWriter @@ -16,9 +17,11 @@ class JpqlPathPropertySerializer : JpqlSerializer> { override fun serialize(part: JpqlPathProperty<*, *>, writer: JpqlWriter, context: RenderContext) { val delegate = context.getValue(JpqlRenderSerializer) + val introspector = context.getValue(JpqlRenderIntrospector) + val property = introspector.introspect(part.property) delegate.serialize(part.path, writer, context) writer.write(".") - writer.write(part.property.name) + writer.write(property.name) } } diff --git a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/CombinedJpqlIntrospectorTest.kt b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/CombinedJpqlIntrospectorTest.kt index 3ff8d2366..e8d529949 100644 --- a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/CombinedJpqlIntrospectorTest.kt +++ b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/CombinedJpqlIntrospectorTest.kt @@ -9,6 +9,8 @@ import org.assertj.core.api.WithAssertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith +import kotlin.reflect.KCallable +import kotlin.reflect.KClass @ExtendWith(MockKExtension::class) class CombinedJpqlIntrospectorTest : WithAssertions { @@ -24,6 +26,10 @@ class CombinedJpqlIntrospectorTest : WithAssertions { override val name: String = "entityName1" } + private val propertyDescription1 = object : JpqlPropertyDescription { + override val name: String = "propertyName1" + } + @BeforeEach fun setUp() { sut = CombinedJpqlIntrospector( @@ -33,9 +39,9 @@ class CombinedJpqlIntrospectorTest : WithAssertions { } @Test - fun `introspect() return the description of the primary, when the primary returns non null`() { + fun `introspect(type) return the description of the primary, when the primary returns non null`() { // given - every { introspector1.introspect(any()) } returns entityDescription1 + every { introspector1.introspect(any>()) } returns entityDescription1 // when val actual = sut.introspect(Book::class) @@ -49,10 +55,10 @@ class CombinedJpqlIntrospectorTest : WithAssertions { } @Test - fun `introspect() return the description of the secondary, when the primary returns null`() { + fun `introspect(type) return the description of the secondary, when the primary returns null`() { // given - every { introspector1.introspect(any()) } returns null - every { introspector2.introspect(any()) } returns entityDescription1 + every { introspector1.introspect(any>()) } returns null + every { introspector2.introspect(any>()) } returns entityDescription1 // when val actual = sut.introspect(Book::class) @@ -65,4 +71,38 @@ class CombinedJpqlIntrospectorTest : WithAssertions { introspector2.introspect(Book::class) } } + + @Test + fun `introspect(property) return the description of the primary, when the primary returns non null`() { + // given + every { introspector1.introspect(any>()) } returns propertyDescription1 + + // when + val actual = sut.introspect(Book::title) + + // then + assertThat(actual).isEqualTo(propertyDescription1) + + verifySequence { + introspector1.introspect(Book::title) + } + } + + @Test + fun `introspect(property) return the description of the secondary, when the primary returns null`() { + // given + every { introspector1.introspect(any>()) } returns null + every { introspector2.introspect(any>()) } returns propertyDescription1 + + // when + val actual = sut.introspect(Book::title) + + // then + assertThat(actual).isEqualTo(propertyDescription1) + + verifySequence { + introspector1.introspect(Book::title) + introspector2.introspect(Book::title) + } + } } diff --git a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/JakartaJpqlIntrospectorTest.kt b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/JakartaJpqlIntrospectorTest.kt index 151b67866..743e544c0 100644 --- a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/JakartaJpqlIntrospectorTest.kt +++ b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/JakartaJpqlIntrospectorTest.kt @@ -11,7 +11,7 @@ class JakartaJpqlIntrospectorTest : WithAssertions { } @Test - fun introspect() { + fun `introspect() returns name of entity annotation, when entity annotation has name`() { // given val type = EntityClass1::class diff --git a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/JavaxJpqlIntrospectorTest.kt b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/JavaxJpqlIntrospectorTest.kt index 46e8b1dac..4b161c54d 100644 --- a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/JavaxJpqlIntrospectorTest.kt +++ b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/JavaxJpqlIntrospectorTest.kt @@ -11,7 +11,7 @@ class JavaxJpqlIntrospectorTest : WithAssertions { } @Test - fun introspect() { + fun `introspect() returns name of entity annotation, when entity annotation has name`() { // given val type = EntityClass1::class diff --git a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/KotlinStyleJpqlPropertyIntrospectorTest.kt b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/KotlinStyleJpqlPropertyIntrospectorTest.kt new file mode 100644 index 000000000..e5bff4570 --- /dev/null +++ b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/introspector/impl/KotlinStyleJpqlPropertyIntrospectorTest.kt @@ -0,0 +1,80 @@ +package com.linecorp.kotlinjdsl.render.jpql.introspector.impl + +import io.mockk.mockkClass +import org.assertj.core.api.WithAssertions +import org.junit.jupiter.api.Test +import kotlin.reflect.KProperty0 + +class KotlinStyleJpqlPropertyIntrospectorTest : WithAssertions { + private val sut = KotlinStyleJpqlPropertyIntrospector() + + @Test + fun `introspect() returns property name, when property is KProperty1`() { + // given + val property = EntityClass1::property1 + + // when + val actual = sut.introspect(property) + + // then + assertThat(actual?.name).isEqualTo("property1") + } + + @Test + fun `introspect() returns property name with prefix removed, when getter name starts with get`() { + // given + val property = EntityClass1::getProperty2 + + // when + val actual = sut.introspect(property) + + // then + assertThat(actual?.name).isEqualTo("property2") + } + + @Test + fun `introspect() returns property name as is, when getter name starts with is`() { + // given + val property = EntityClass1::isProperty3 + + // when + val actual = sut.introspect(property) + + // then + assertThat(actual?.name).isEqualTo("isProperty3") + } + + @Test + fun `introspect() returns property name as is, when getter name does not start with get or is`() { + // given + val property = EntityClass1::someProperty + + // when + val actual = sut.introspect(property) + + // then + assertThat(actual?.name).isEqualTo("someProperty") + } + + @Test + fun `introspect() returns null, when property is not KProperty1 or KFunction1`() { + // given + val property = mockkClass(KProperty0::class) + + // when + val actual = sut.introspect(property) + + // then + assertThat(actual?.name).isNull() + } + + private class EntityClass1 { + val property1: Long = 0 + + fun getProperty2(): Long = 100 + + fun isProperty3(): Boolean = true + + fun someProperty(): String = "someProperty" + } +} diff --git a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlEntityPropertySerializerTest.kt b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlEntityPropertySerializerTest.kt index 2dcaa0736..d89a63203 100644 --- a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlEntityPropertySerializerTest.kt +++ b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlEntityPropertySerializerTest.kt @@ -5,13 +5,17 @@ import com.linecorp.kotlinjdsl.querymodel.jpql.path.Paths import com.linecorp.kotlinjdsl.querymodel.jpql.path.impl.JpqlEntityProperty import com.linecorp.kotlinjdsl.render.TestRenderContext import com.linecorp.kotlinjdsl.render.jpql.entity.book.Book +import com.linecorp.kotlinjdsl.render.jpql.introspector.JpqlPropertyDescription +import com.linecorp.kotlinjdsl.render.jpql.introspector.JpqlRenderIntrospector import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlRenderSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlSerializerTest import com.linecorp.kotlinjdsl.render.jpql.writer.JpqlWriter +import io.mockk.every import io.mockk.impl.annotations.MockK import io.mockk.verifySequence import org.assertj.core.api.WithAssertions import org.junit.jupiter.api.Test +import kotlin.reflect.KCallable @JpqlSerializerTest class JpqlEntityPropertySerializerTest : WithAssertions { @@ -20,11 +24,17 @@ class JpqlEntityPropertySerializerTest : WithAssertions { @MockK private lateinit var writer: JpqlWriter + @MockK + private lateinit var introspector: JpqlRenderIntrospector + @MockK private lateinit var serializer: JpqlRenderSerializer private val entity1 = Entities.entity(Book::class, "book01") private val property1 = Book::price + private val propertyDescription1 = object : JpqlPropertyDescription { + override val name = property1.name + } @Test fun handledType() { @@ -38,11 +48,13 @@ class JpqlEntityPropertySerializerTest : WithAssertions { @Test fun serialize() { // given + every { introspector.introspect(any>()) } returns propertyDescription1 + val part = Paths.path( entity1, property1, ) - val context = TestRenderContext(serializer) + val context = TestRenderContext(introspector, serializer) // when sut.serialize(part as JpqlEntityProperty<*, *>, writer, context) @@ -51,7 +63,7 @@ class JpqlEntityPropertySerializerTest : WithAssertions { verifySequence { writer.write(entity1.alias) writer.write(".") - writer.write(property1.name) + writer.write(propertyDescription1.name) } } } diff --git a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlEntitySerializerTest.kt b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlEntitySerializerTest.kt index 9835dd9c8..c022a7bad 100644 --- a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlEntitySerializerTest.kt +++ b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlEntitySerializerTest.kt @@ -18,6 +18,7 @@ import io.mockk.verifySequence import org.assertj.core.api.WithAssertions import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest +import kotlin.reflect.KClass @JpqlSerializerTest internal class JpqlEntitySerializerTest : WithAssertions { @@ -57,7 +58,7 @@ internal class JpqlEntitySerializerTest : WithAssertions { clause: JpqlRenderClause, ) { // given - every { introspector.introspect(any()) } returns entityDescription1 + every { introspector.introspect(any>()) } returns entityDescription1 val part = Entities.entity(Book::class, alias1) val context = TestRenderContext(introspector, statement, clause) diff --git a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlEntityTreatSerializerTest.kt b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlEntityTreatSerializerTest.kt index 53c04122c..d4c98a7bb 100644 --- a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlEntityTreatSerializerTest.kt +++ b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlEntityTreatSerializerTest.kt @@ -19,6 +19,7 @@ import io.mockk.verifySequence import org.assertj.core.api.WithAssertions import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest +import kotlin.reflect.KClass @JpqlSerializerTest class JpqlEntityTreatSerializerTest : WithAssertions { @@ -58,7 +59,7 @@ class JpqlEntityTreatSerializerTest : WithAssertions { clause: JpqlRenderClause, ) { // given - every { introspector.introspect(any()) } returns entityDescription1 + every { introspector.introspect(any>()) } returns entityDescription1 val part = Entities.treat( entity1, @@ -93,7 +94,7 @@ class JpqlEntityTreatSerializerTest : WithAssertions { clause: JpqlRenderClause, ) { // given - every { introspector.introspect(any()) } returns entityDescription1 + every { introspector.introspect(any>()) } returns entityDescription1 val part = Entities.treat( entity1, diff --git a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPathPropertySerializerTest.kt b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPathPropertySerializerTest.kt index ee3eabc37..cc8cc1aeb 100644 --- a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPathPropertySerializerTest.kt +++ b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPathPropertySerializerTest.kt @@ -5,13 +5,17 @@ import com.linecorp.kotlinjdsl.querymodel.jpql.path.impl.JpqlPathProperty import com.linecorp.kotlinjdsl.render.TestRenderContext import com.linecorp.kotlinjdsl.render.jpql.entity.book.Book import com.linecorp.kotlinjdsl.render.jpql.entity.book.Isbn +import com.linecorp.kotlinjdsl.render.jpql.introspector.JpqlPropertyDescription +import com.linecorp.kotlinjdsl.render.jpql.introspector.JpqlRenderIntrospector import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlRenderSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlSerializerTest import com.linecorp.kotlinjdsl.render.jpql.writer.JpqlWriter +import io.mockk.every import io.mockk.impl.annotations.MockK import io.mockk.verifySequence import org.assertj.core.api.WithAssertions import org.junit.jupiter.api.Test +import kotlin.reflect.KCallable @JpqlSerializerTest class JpqlPathPropertySerializerTest : WithAssertions { @@ -20,6 +24,9 @@ class JpqlPathPropertySerializerTest : WithAssertions { @MockK private lateinit var writer: JpqlWriter + @MockK + private lateinit var introspector: JpqlRenderIntrospector + @MockK private lateinit var serializer: JpqlRenderSerializer @@ -27,6 +34,10 @@ class JpqlPathPropertySerializerTest : WithAssertions { private val property1 = Isbn::value + private val propertyDescription1 = object : JpqlPropertyDescription { + override val name = property1.name + } + @Test fun handledType() { // when @@ -39,11 +50,13 @@ class JpqlPathPropertySerializerTest : WithAssertions { @Test fun serialize() { // given + every { introspector.introspect(any>()) } returns propertyDescription1 + val part = Paths.path( path1, property1, ) - val context = TestRenderContext(serializer) + val context = TestRenderContext(introspector, serializer) // when sut.serialize(part as JpqlPathProperty<*, *>, writer, context) @@ -52,7 +65,7 @@ class JpqlPathPropertySerializerTest : WithAssertions { verifySequence { serializer.serialize(path1, writer, context) writer.write(".") - writer.write(property1.name) + writer.write(propertyDescription1.name) } } } diff --git a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPathTreatSerializerTest.kt b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPathTreatSerializerTest.kt index 6c42ec983..ebf723642 100644 --- a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPathTreatSerializerTest.kt +++ b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPathTreatSerializerTest.kt @@ -15,6 +15,7 @@ import io.mockk.impl.annotations.MockK import io.mockk.verifySequence import org.assertj.core.api.WithAssertions import org.junit.jupiter.api.Test +import kotlin.reflect.KClass @JpqlSerializerTest class JpqlPathTreatSerializerTest : WithAssertions { @@ -47,7 +48,7 @@ class JpqlPathTreatSerializerTest : WithAssertions { @Test fun serialize() { // given - every { introspector.introspect(any()) } returns entityDescription1 + every { introspector.introspect(any>()) } returns entityDescription1 val part = Paths.treat( path1, diff --git a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlValueSerializerTest.kt b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlValueSerializerTest.kt index 67450a9bb..494539b2f 100644 --- a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlValueSerializerTest.kt +++ b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlValueSerializerTest.kt @@ -13,6 +13,7 @@ import io.mockk.impl.annotations.MockK import io.mockk.verifySequence import org.assertj.core.api.WithAssertions import org.junit.jupiter.api.Test +import kotlin.reflect.KClass @JpqlSerializerTest class JpqlValueSerializerTest : WithAssertions { @@ -59,7 +60,7 @@ class JpqlValueSerializerTest : WithAssertions { @Test fun `serialize() draws entity name, when value is KClass`() { // given - every { introspector.introspect(any()) } returns entityDescription1 + every { introspector.introspect(any>()) } returns entityDescription1 val part = Expressions.value( Book::class,