Skip to content

Commit

Permalink
gh-2: uses jsonb instead of a string to hold the board information.
Browse files Browse the repository at this point in the history
  • Loading branch information
pmhsfelix committed Oct 10, 2022
1 parent 9cecca4 commit 13d101b
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 7 deletions.
5 changes: 3 additions & 2 deletions code/tic-tac-tow-service/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ dependencies {
implementation("org.springframework.security:spring-security-core:5.7.3")

// for JDBI
implementation("org.jdbi:jdbi3-core:3.32.0")
implementation("org.jdbi:jdbi3-kotlin:3.32.0")
implementation("org.jdbi:jdbi3-core:3.33.0")
implementation("org.jdbi:jdbi3-kotlin:3.33.0")
implementation("org.jdbi:jdbi3-postgres:3.33.0")
implementation("org.postgresql:postgresql:42.5.0")

testImplementation("org.springframework.boot:spring-boot-starter-test")
Expand Down
2 changes: 1 addition & 1 deletion code/tic-tac-tow-service/sql/create-schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ create table dbo.Tokens(
create table dbo.Games(
id UUID not null,
state VARCHAR(64) not null,
board CHAR(9) not null,
board jsonb not null,
created int not null,
updated int not null,
deadline int,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package pt.isel.daw.tictactow.domain

data class Board(
private val cells: Array<Array<State>>
val cells: Array<Array<State>>
) {
init {
require(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package pt.isel.daw.tictactow.repository.jdbi

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.KotlinModule
import org.jdbi.v3.core.Handle
import org.jdbi.v3.core.kotlin.mapTo
import org.jdbi.v3.core.mapper.Nested
import org.jdbi.v3.core.statement.Update
import org.postgresql.util.PGobject
import pt.isel.daw.tictactow.domain.Board
import pt.isel.daw.tictactow.domain.Game
import pt.isel.daw.tictactow.domain.User
Expand All @@ -23,7 +27,7 @@ class JdbiGamesRepository(
)
.bind("id", game.id)
.bind("state", game.state)
.bind("board", game.board.toString())
.bindBoard("board", game.board)
.bind("created", game.created.epochSecond)
.bind("updated", game.updated.epochSecond)
.bind("deadline", game.deadline?.epochSecond)
Expand Down Expand Up @@ -61,11 +65,31 @@ class JdbiGamesRepository(
)
.bind("id", game.id)
.bind("state", game.state)
.bind("board", game.board.toString())
.bindBoard("board", game.board)
.bind("updated", game.updated.epochSecond)
.bind("deadline", game.deadline?.epochSecond)
.execute()
}

companion object {
private fun Update.bindBoard(name: String, board: Board) = run {
bind(
name,
PGobject().apply {
type = "jsonb"
value = serializeBoardToJson(board)
}
)
}

private val objectMapper = ObjectMapper().registerModule(KotlinModule.Builder().build())

private fun serializeBoardToJson(board: Board): String = objectMapper.writeValueAsString(board.cells)

fun deserializeBoardFromJson(json: String) = Board(
objectMapper.readValue(json, Array<Array<Board.State>>::class.java)
)
}
}

class GameDbModel(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package pt.isel.daw.tictactow.repository.jdbi

import org.jdbi.v3.core.Jdbi
import org.jdbi.v3.core.kotlin.KotlinPlugin
import org.jdbi.v3.postgres.PostgresPlugin
import pt.isel.daw.tictactow.repository.jdbi.mappers.BoardMapper
import pt.isel.daw.tictactow.repository.jdbi.mappers.InstantMapper
import pt.isel.daw.tictactow.repository.jdbi.mappers.PasswordValidationInfoMapper
import pt.isel.daw.tictactow.repository.jdbi.mappers.TokenValidationInfoMapper

fun Jdbi.configure(): Jdbi {
installPlugin(KotlinPlugin())
installPlugin(PostgresPlugin())

registerColumnMapper(PasswordValidationInfoMapper())
registerColumnMapper(TokenValidationInfoMapper())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package pt.isel.daw.tictactow.repository.jdbi.mappers

import org.jdbi.v3.core.mapper.ColumnMapper
import org.jdbi.v3.core.statement.StatementContext
import org.postgresql.util.PGobject
import pt.isel.daw.tictactow.domain.Board
import pt.isel.daw.tictactow.repository.jdbi.JdbiGamesRepository
import java.sql.ResultSet
import java.sql.SQLException

class BoardMapper : ColumnMapper<Board> {
@Throws(SQLException::class)
override fun map(r: ResultSet, columnNumber: Int, ctx: StatementContext?): Board {
return Board.fromString(r.getString(columnNumber))
val obj = r.getObject(columnNumber, PGobject::class.java)
return JdbiGamesRepository.deserializeBoardFromJson(obj.value ?: throw IllegalArgumentException("TODO"))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.fail
import org.junit.jupiter.api.Test
import pt.isel.daw.tictactow.RealClock
import pt.isel.daw.tictactow.domain.Board
import pt.isel.daw.tictactow.domain.GameLogic
import pt.isel.daw.tictactow.domain.PasswordValidationInfo
import pt.isel.daw.tictactow.domain.Position
import pt.isel.daw.tictactow.repository.jdbi.JdbiGamesRepository
import pt.isel.daw.tictactow.repository.jdbi.JdbiUsersRepository
import pt.isel.daw.tictactow.utils.testWithHandleAndRollback
Expand Down Expand Up @@ -36,5 +38,17 @@ class GameRepositoryTests {

// then: the two games are equal
assertEquals(game, retrievedGame)

// when: updating the game
val newGame = game.copy(board = game.board.mutate(Position(1, 1), Board.State.PLAYER_X))

// and: storing the game
gameRepo.update(newGame)

// and: retrieving the game again
val newRetrievedGame = gameRepo.getById(game.id)

// then: the two games are equal
assertEquals(newGame, newRetrievedGame)
}
}

0 comments on commit 13d101b

Please sign in to comment.