Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Session] 세션 data layer 구현 #62

Merged
merged 13 commits into from
Jul 22, 2023
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ plugins {
configureHiltAndroid()

dependencies {
implementation(project(":core:model"))
implementation(project(":core:designsystem"))
implementation(project(":core:domain"))
implementation(project(":core:navigation"))
Expand Down
3 changes: 3 additions & 0 deletions core/data/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ android {
}

dependencies {
implementation(project(":core:model"))

implementation(libs.retrofit.core)
implementation(libs.retrofit.kotlin.serialization)
implementation(libs.okhttp.logging)
implementation(libs.kotlinx.serialization.json)
implementation(libs.kotlinx.datetime)
}
34 changes: 34 additions & 0 deletions core/data/src/main/assets/sessions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[
{
"title": "Keynote",
"content": [],
"speakers": [],
"level": "기타",
"tags": [
"키노트"
],
"room": null,
"startTime": "2023-09-12T13:00:00.000",
"endTime": "2023-09-12T13:20:00.000"
},
{
"title": "Jetpack Compose로 Android UI 개발하기",
"content": [
"Jetpack Compose는 네이티브 UI를 빌드하기 위한 Android의 최신 권장 도구 키트입니다."
],
"speakers": [
{
"name": "김컴포즈",
"imageUrl": "https://developer.android.com/static/courses/android-basics-compose/images/hero-assets/unit-logo.svg"
}
],
"level": "고급",
"tags": [
"Jetpack",
"UI"
],
"room": "Track1",
"startTime": "2023-09-12T13:25:00.000",
"endTime": "2023-09-12T13:55:00.000"
}
]
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package com.droidknights.app2023.core.data.api

import com.droidknights.app2023.core.data.api.model.SessionResponse
import com.droidknights.app2023.core.data.api.model.SponsorResponse
import retrofit2.http.GET

internal interface GithubRawApi {

@GET("/droidknights/DroidKnights2023_App/main/data/src/main/assets/sponsors.json")
suspend fun getSponsors(): List<SponsorResponse>

@GET("/droidknights/DroidKnights2023_App/main/data/src/main/assets/sessions.json")
suspend fun getSessions(): List<SessionResponse>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,28 @@ package com.droidknights.app2023.core.data.api.fake

import android.content.Context
import com.droidknights.app2023.core.data.api.GithubRawApi
import com.droidknights.app2023.core.data.api.model.SessionResponse
import com.droidknights.app2023.core.data.api.model.SponsorResponse
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream

@OptIn(ExperimentalSerializationApi::class)
internal class AssetsGithubRawApi(
context: Context,
private val json: Json = Json { ignoreUnknownKeys = true },
private val json: Json = Json {
ignoreUnknownKeys = true
coerceInputValues = true
},
) : GithubRawApi {
private val assets = context.assets.open("sponsors.json")

private val sponsors = context.assets.open("sponsors.json")
private val sessions = context.assets.open("sessions.json")

override suspend fun getSponsors(): List<SponsorResponse> {
return json.decodeFromStream(assets)
return json.decodeFromStream(sponsors)
}

override suspend fun getSessions(): List<SessionResponse> {
return json.decodeFromStream(sessions)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.droidknights.app2023.core.data.api.model

import com.droidknights.app2023.core.model.Level
import com.droidknights.app2023.core.model.Room
import com.droidknights.app2023.core.model.Speaker
import com.droidknights.app2023.core.model.Tag
import kotlinx.datetime.LocalDateTime
import kotlinx.serialization.Serializable

@Serializable
internal data class SessionResponse(
val title: String,
val content: List<String>,
val speakers: List<Speaker>,
val level: Level = Level.ETC,
val tags: List<Tag> = emptyList(),
val room: Room = Room.ETC,
val startTime: LocalDateTime,
val endTime: LocalDateTime,
)
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.droidknights.app2023.core.data.mapper

import com.droidknights.app2023.core.data.model.ContributorEntity
import com.droidknights.app2023.core.data.api.model.ContributorResponse
import com.droidknights.app2023.core.model.Contributor

internal fun ContributorResponse.toData(): ContributorEntity =
ContributorEntity(
internal fun ContributorResponse.toData(): Contributor =
Contributor(
name = this.name,
imageUrl = this.imageUrl
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.droidknights.app2023.core.data.mapper

import com.droidknights.app2023.core.data.api.model.SessionResponse
import com.droidknights.app2023.core.model.Session

internal fun SessionResponse.toData(): Session = Session(
title = this.title,
content = this.content,
speakers = this.speakers,
level = this.level,
tags = this.tags,
room = this.room,
startTime = this.startTime,
endTime = this.endTime
)
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.droidknights.app2023.core.data.mapper

import com.droidknights.app2023.core.data.api.model.SponsorResponse
import com.droidknights.app2023.core.data.model.SponsorEntity
import com.droidknights.app2023.core.model.Sponsor

internal fun SponsorResponse.toData(): SponsorEntity = SponsorEntity(
internal fun SponsorResponse.toData(): Sponsor = Sponsor(
name = name,
imageUrl = imageUrl,
homepage = homepage,
grade = when (grade) {
SponsorResponse.Grade.PLATINUM -> SponsorEntity.Grade.PLATINUM
SponsorResponse.Grade.GOLD -> SponsorEntity.Grade.GOLD
SponsorResponse.Grade.PLATINUM -> Sponsor.Grade.PLATINUM
SponsorResponse.Grade.GOLD -> Sponsor.Grade.GOLD
}
)

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.droidknights.app2023.core.data.repository

import com.droidknights.app2023.core.data.model.ContributorEntity
import com.droidknights.app2023.core.model.Contributor

interface ContributorRepository {

suspend fun getContributors(
owner: String,
name: String,
): List<ContributorEntity>
): List<Contributor>
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.droidknights.app2023.core.data.repository

import com.droidknights.app2023.core.data.model.ContributorEntity
import com.droidknights.app2023.core.data.api.GithubApi
import com.droidknights.app2023.core.data.mapper.toData
import com.droidknights.app2023.core.model.Contributor
import javax.inject.Inject

internal class DefaultContributorRepository @Inject constructor(
Expand All @@ -12,7 +12,7 @@ internal class DefaultContributorRepository @Inject constructor(
override suspend fun getContributors(
owner: String,
name: String,
): List<ContributorEntity> {
): List<Contributor> {
return githubApi.getContributors(owner, name)
.map { it.toData() }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.droidknights.app2023.core.data.repository

import com.droidknights.app2023.core.data.api.GithubRawApi
import com.droidknights.app2023.core.data.mapper.toData
import com.droidknights.app2023.core.model.Session
import javax.inject.Inject

internal class DefaultSessionRepository @Inject constructor(
private val githubRawApi: GithubRawApi,
) : SessionRepository {

override suspend fun getSessions(): List<Session> {
return githubRawApi.getSessions().map { it.toData() }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ package com.droidknights.app2023.core.data.repository

import com.droidknights.app2023.core.data.api.GithubRawApi
import com.droidknights.app2023.core.data.mapper.toData
import com.droidknights.app2023.core.data.model.SponsorEntity
import com.droidknights.app2023.core.model.Sponsor
import javax.inject.Inject

internal class DefaultSponsorRepository @Inject constructor(
private val githubRawApi: GithubRawApi,
) : SponsorRepository {
override suspend fun getSponsors(): List<SponsorEntity> {

override suspend fun getSponsors(): List<Sponsor> {
return githubRawApi.getSponsors().map { it.toData() }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.droidknights.app2023.core.data.repository

import com.droidknights.app2023.core.model.Session

interface SessionRepository {

suspend fun getSessions(): List<Session>
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.droidknights.app2023.core.data.repository

import com.droidknights.app2023.core.data.model.SponsorEntity
import com.droidknights.app2023.core.model.Sponsor

interface SponsorRepository {
suspend fun getSponsors(): List<SponsorEntity>

suspend fun getSponsors(): List<Sponsor>
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
package com.droidknights.app2023.core.data.api.fake

import com.droidknights.app2023.core.data.api.GithubRawApi
import com.droidknights.app2023.core.data.api.model.SessionResponse
import com.droidknights.app2023.core.data.api.model.SponsorResponse
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream
import java.io.File

@OptIn(ExperimentalSerializationApi::class)
internal class FakeGithubRawApi(
private val json: Json = Json { ignoreUnknownKeys = true },
private val json: Json = Json {
ignoreUnknownKeys = true
coerceInputValues = true
},
) : GithubRawApi {
private val assets = File("src/main/assets/sponsors.json")

private val sponsors = File("src/main/assets/sponsors.json")
private val sessions = File("src/main/assets/sessions.json")

override suspend fun getSponsors(): List<SponsorResponse> {
return json.decodeFromStream(assets.inputStream())
return json.decodeFromStream(sponsors.inputStream())
}

override suspend fun getSessions(): List<SessionResponse> {
return json.decodeFromStream(sessions.inputStream())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.droidknights.app2023.core.data.repository

import com.droidknights.app2023.core.data.api.fake.FakeGithubApi
import com.droidknights.app2023.core.data.api.model.ContributorResponse
import com.droidknights.app2023.core.data.model.ContributorEntity
import com.droidknights.app2023.core.model.Contributor
import io.kotest.core.spec.style.BehaviorSpec
import io.kotest.matchers.shouldBe

Expand All @@ -18,7 +18,7 @@ internal class DefaultContributorRepositoryTest : BehaviorSpec() {
val expected = contributors

When("기여자를 조회한다") {
val contributors: List<ContributorEntity> = repository.getContributors(
val contributors: List<Contributor> = repository.getContributors(
owner = "droidknights",
name = "app2023"
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.droidknights.app2023.core.data.repository

import com.droidknights.app2023.core.data.api.fake.FakeGithubRawApi
import com.droidknights.app2023.core.model.Level
import com.droidknights.app2023.core.model.Room
import com.droidknights.app2023.core.model.Session
import com.droidknights.app2023.core.model.Speaker
import com.droidknights.app2023.core.model.Tag
import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe
import kotlinx.datetime.LocalDateTime

internal class DefaultSessionRepositoryTest : StringSpec() {

init {
val repository: SessionRepository = DefaultSessionRepository(
githubRawApi = FakeGithubRawApi()
)
"역직렬화 테스트" {
val expected = listOf(
Session(
title = "Keynote",
content = listOf(),
speakers = listOf(),
level = Level.ETC,
tags = listOf(Tag("키노트")),
room = Room.ETC,
startTime = LocalDateTime(2023, 9, 12, 13, 0),
endTime = LocalDateTime(2023, 9, 12, 13, 20),
),
Session(
title = "Jetpack Compose로 Android UI 개발하기",
content = listOf("Jetpack Compose는 네이티브 UI를 빌드하기 위한 Android의 최신 권장 도구 키트입니다."),
speakers = listOf(
Speaker(
name = "김컴포즈",
imageUrl = "https://developer.android.com/static/courses/android-basics-compose/images/hero-assets/unit-logo.svg",
)
),
level = Level.ADVANCED,
tags = listOf(
Tag("Jetpack"),
Tag("UI"),
),
room = Room.TRACK1,
startTime = LocalDateTime(2023, 9, 12, 13, 25),
endTime = LocalDateTime(2023, 9, 12, 13, 55),
),
)
val actual = repository.getSessions()
actual shouldBe expected
}
}
}
Loading