refactor: Uri型のColumnTypeを作成して型安全性を向上

This commit is contained in:
usbharu 2024-09-11 08:09:01 +09:00
parent 498d6d73da
commit 34a36b5ed5
Signed by: usbharu
GPG Key ID: 6556747BF94EEBC8
4 changed files with 38 additions and 16 deletions

View File

@ -0,0 +1,22 @@
package dev.usbharu.hideout.core.infrastructure.exposed
import org.jetbrains.exposed.sql.Column
import org.jetbrains.exposed.sql.ColumnType
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.vendors.currentDialect
import java.net.URI
class UriColumnType(val colLength: Int) : ColumnType<URI>() {
override fun sqlType(): String = currentDialect.dataTypeProvider.varcharType(colLength)
override fun valueFromDB(value: Any): URI? = when (value) {
is URI -> value
is String -> URI(value)
is CharSequence -> URI(value.toString())
else -> error("Unexpected value of type String: $value of ${value::class.qualifiedName}")
}
override fun notNullValueToDB(value: URI): Any = value.toString()
}
fun Table.uri(name: String, colLength: Int): Column<URI> = registerColumn(name, UriColumnType(colLength))

View File

@ -92,7 +92,7 @@ class ExposedUserTimelineQueryService : UserTimelineQueryService, AbstractReposi
screenName = it[Actors.screenName], screenName = it[Actors.screenName],
url = URI.create(it[Actors.url]), url = URI.create(it[Actors.url]),
locked = it[Actors.locked], locked = it[Actors.locked],
icon = it.getOrNull(iconMedia[Media.url])?.let { URI.create(it) } icon = it.getOrNull(iconMedia[Media.url])
), ),
overview = it[authorizedQuery[Posts.overview]], overview = it[authorizedQuery[Posts.overview]],
text = it[authorizedQuery[Posts.text]], text = it[authorizedQuery[Posts.text]],

View File

@ -18,12 +18,12 @@ package dev.usbharu.hideout.core.infrastructure.exposedrepository
import dev.usbharu.hideout.core.domain.model.actor.ActorId import dev.usbharu.hideout.core.domain.model.actor.ActorId
import dev.usbharu.hideout.core.domain.model.media.* import dev.usbharu.hideout.core.domain.model.media.*
import dev.usbharu.hideout.core.infrastructure.exposed.uri
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.stereotype.Repository import org.springframework.stereotype.Repository
import java.net.URI
import dev.usbharu.hideout.core.domain.model.media.Media as EntityMedia import dev.usbharu.hideout.core.domain.model.media.Media as EntityMedia
@Repository @Repository
@ -35,9 +35,9 @@ class ExposedMediaRepository : MediaRepository, AbstractRepository() {
Media.upsert { Media.upsert {
it[id] = media.id.id it[id] = media.id.id
it[name] = media.name.name it[name] = media.name.name
it[url] = media.url.toString() it[url] = media.url
it[remoteUrl] = media.remoteUrl?.toString() it[remoteUrl] = media.remoteUrl
it[thumbnailUrl] = media.thumbnailUrl?.toString() it[thumbnailUrl] = media.thumbnailUrl
it[type] = media.type.name it[type] = media.type.name
it[blurhash] = media.blurHash?.hash it[blurhash] = media.blurHash?.hash
it[mimeType] = media.mimeType.type + "/" + media.mimeType.subtype it[mimeType] = media.mimeType.type + "/" + media.mimeType.subtype
@ -83,9 +83,9 @@ fun ResultRow.toMedia(): EntityMedia {
return EntityMedia( return EntityMedia(
id = MediaId(this[Media.id]), id = MediaId(this[Media.id]),
name = MediaName(this[Media.name]), name = MediaName(this[Media.name]),
url = URI.create(this[Media.url]), url = this[Media.url],
remoteUrl = this[Media.remoteUrl]?.let { URI.create(it) }, remoteUrl = this[Media.remoteUrl],
thumbnailUrl = this[Media.thumbnailUrl]?.let { URI.create(it) }, thumbnailUrl = this[Media.thumbnailUrl],
type = fileType, type = fileType,
blurHash = this[Media.blurhash]?.let { MediaBlurHash(it) }, blurHash = this[Media.blurhash]?.let { MediaBlurHash(it) },
mimeType = MimeType(mimeType.substringBefore("/"), mimeType.substringAfter("/"), fileType), mimeType = MimeType(mimeType.substringBefore("/"), mimeType.substringAfter("/"), fileType),
@ -100,9 +100,9 @@ fun ResultRow.toMediaOrNull(): EntityMedia? {
return EntityMedia( return EntityMedia(
id = MediaId(this.getOrNull(Media.id) ?: return null), id = MediaId(this.getOrNull(Media.id) ?: return null),
name = MediaName(this.getOrNull(Media.name) ?: return null), name = MediaName(this.getOrNull(Media.name) ?: return null),
url = URI.create(this.getOrNull(Media.url) ?: return null), url = this.getOrNull(Media.url) ?: return null,
remoteUrl = this[Media.remoteUrl]?.let { URI.create(it) }, remoteUrl = this[Media.remoteUrl],
thumbnailUrl = this[Media.thumbnailUrl]?.let { URI.create(it) }, thumbnailUrl = this[Media.thumbnailUrl],
type = FileType.valueOf(this[Media.type]), type = FileType.valueOf(this[Media.type]),
blurHash = this[Media.blurhash]?.let { MediaBlurHash(it) }, blurHash = this[Media.blurhash]?.let { MediaBlurHash(it) },
mimeType = MimeType(mimeType.substringBefore("/"), mimeType.substringAfter("/"), fileType), mimeType = MimeType(mimeType.substringBefore("/"), mimeType.substringAfter("/"), fileType),
@ -114,9 +114,9 @@ fun ResultRow.toMediaOrNull(): EntityMedia? {
object Media : Table("media") { object Media : Table("media") {
val id = long("id") val id = long("id")
val name = varchar("name", 255) val name = varchar("name", 255)
val url = varchar("url", 255).uniqueIndex() val url = uri("url", 255).uniqueIndex()
val remoteUrl = varchar("remote_url", 255).uniqueIndex().nullable() val remoteUrl = uri("remote_url", 255).uniqueIndex().nullable()
val thumbnailUrl = varchar("thumbnail_url", 255).uniqueIndex().nullable() val thumbnailUrl = uri("thumbnail_url", 255).uniqueIndex().nullable()
val type = varchar("type", 100) val type = varchar("type", 100)
val blurhash = varchar("blurhash", 255).nullable() val blurhash = varchar("blurhash", 255).nullable()
val mimeType = varchar("mime_type", 255) val mimeType = varchar("mime_type", 255)

View File

@ -72,7 +72,7 @@ class ExposedMediaRepositoryTest : AbstractRepositoryTest(Media) {
.row(0) .row(0)
.isEqualTo(Media.id, 1) .isEqualTo(Media.id, 1)
.isEqualTo(Media.name, "name") .isEqualTo(Media.name, "name")
.isEqualTo(Media.url, "https://www.example.com") .value(Media.url).isEqualTo("https://www.example.com")
.isEqualTo(Media.remoteUrl, null) .isEqualTo(Media.remoteUrl, null)
.isEqualTo(Media.thumbnailUrl, null) .isEqualTo(Media.thumbnailUrl, null)
.isEqualTo(Media.type, "Audio") .isEqualTo(Media.type, "Audio")
@ -165,7 +165,7 @@ class ExposedMediaRepositoryTest : AbstractRepositoryTest(Media) {
.row(0) .row(0)
.isEqualTo(Media.id, 1) .isEqualTo(Media.id, 1)
.isEqualTo(Media.name, "name") .isEqualTo(Media.name, "name")
.isEqualTo(Media.url, "https://www.example.com") .value(Media.url).isEqualTo("https://www.example.com")
.isEqualTo(Media.remoteUrl, null) .isEqualTo(Media.remoteUrl, null)
.isEqualTo(Media.thumbnailUrl, null) .isEqualTo(Media.thumbnailUrl, null)
.isEqualTo(Media.type, "Audio") .isEqualTo(Media.type, "Audio")