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

[Home] 후원사 목록 data layer 구현 #51

Merged
merged 12 commits into from
Jul 18, 2023
8 changes: 8 additions & 0 deletions core/data/src/main/assets/sponsors.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{
"name": "헤이딜러",
"imageUrl": "https://raw.githubusercontent.com/droidknights/DroidKnights2020_App/master/androidapp/app/src/main/res/drawable-xxxhdpi/ic_sponsor_heydealer.png",
"homepage": "https://heydealer.co.kr/",
"grade": "gold"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.droidknights.app2023.core.data.api

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>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
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.SponsorResponse
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream

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

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

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
internal data class SponsorResponse(
@SerialName("name") val name: String,
@SerialName("imageUrl") val imageUrl: String,
@SerialName("homepage") val homepage: String,
@SerialName("grade") val grade: Grade,
) {

enum class Grade {
@SerialName("platinum")
PLATINUM,

@SerialName("gold")
GOLD,
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.droidknights.app2023.core.data.di

import com.droidknights.app2023.core.data.api.GithubApi
import com.droidknights.app2023.core.data.api.GithubRawApi
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import dagger.Module
import dagger.Provides
Expand Down Expand Up @@ -41,7 +42,18 @@ internal object ApiModule {
.client(okHttpClient).build()
.create(GithubApi::class.java)
}


@Provides
@Singleton
fun provideGitRawApi(
okHttpClient: OkHttpClient,
converterFactory: Converter.Factory,
): GithubRawApi = Retrofit.Builder()
.baseUrl("https://raw.githubusercontent.com/")
.addConverterFactory(converterFactory)
.client(okHttpClient).build()
.create(GithubRawApi::class.java)

@Provides
@Singleton
fun provideJson(): Json = Json {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
package com.droidknights.app2023.core.data.di

import android.content.Context
import com.droidknights.app2023.core.data.api.fake.AssetsGithubRawApi
import com.droidknights.app2023.core.data.repository.ContributorRepository
import com.droidknights.app2023.core.data.repository.DefaultContributorRepository
import com.droidknights.app2023.core.data.repository.DefaultSponsorRepository
import com.droidknights.app2023.core.data.repository.SponsorRepository
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@InstallIn(SingletonComponent::class)
@Module
Expand All @@ -15,4 +22,17 @@ internal abstract class DataModule {
abstract fun bindsContributorRepository(
repository: DefaultContributorRepository,
): ContributorRepository

@InstallIn(SingletonComponent::class)
@Module
internal object FakeModule {

@Provides
@Singleton
fun provideSponsorRepository(
@ApplicationContext context: Context,
): SponsorRepository {
return DefaultSponsorRepository(AssetsGithubRawApi(context))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +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

internal fun SponsorResponse.toData(): SponsorEntity = SponsorEntity(
name = name,
imageUrl = imageUrl,
homepage = homepage,
grade = when (grade) {
SponsorResponse.Grade.PLATINUM -> SponsorEntity.Grade.PLATINUM
SponsorResponse.Grade.GOLD -> SponsorEntity.Grade.GOLD
}
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.droidknights.app2023.core.data.model

data class SponsorEntity(
val name: String,
val imageUrl: String,
val homepage: String,
val grade: Grade,
) {
enum class Grade { PLATINUM, GOLD, }
}
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.data.model.SponsorEntity
import javax.inject.Inject

internal class DefaultSponsorRepository @Inject constructor(
private val githubRawApi: GithubRawApi,
) : SponsorRepository {

override suspend fun getSponsors(): List<SponsorEntity> {
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.data.model.SponsorEntity

interface SponsorRepository {

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

import com.droidknights.app2023.core.data.api.model.ContributorResponse
import com.droidknights.app2023.core.data.api.GithubApi
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.droidknights.app2023.core.data.api.fake

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

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

override suspend fun getSponsors(): List<SponsorResponse> {
return json.decodeFromStream(assets.inputStream())
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
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 io.kotest.core.spec.style.BehaviorSpec
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.droidknights.app2023.core.data.repository

import com.droidknights.app2023.core.data.api.fake.FakeGithubRawApi
import com.droidknights.app2023.core.data.model.SponsorEntity
import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe
import kotlinx.serialization.json.Json

internal class DefaultSponsorRepositoryTest : StringSpec() {

init {
val repository: SponsorRepository = DefaultSponsorRepository(
githubRawApi = FakeGithubRawApi(
json = Json { ignoreUnknownKeys = true },
)
)
"역직렬화 테스트" {
val expected = SponsorEntity(
name = "헤이딜러",
imageUrl = "https://raw.githubusercontent.com/droidknights/DroidKnights2020_App/master/androidapp/app/src/main/res/drawable-xxxhdpi/ic_sponsor_heydealer.png",
homepage = "https://heydealer.co.kr/",
grade = SponsorEntity.Grade.GOLD,
)
val actual = repository.getSponsors().first()
actual shouldBe expected
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.droidknights.app2023.core.domain.mapper

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

internal fun SponsorEntity.toDomain(): Sponsor = Sponsor(
name = name,
imageUrl = imageUrl,
homepage = homepage,
grade = when (grade) {
SponsorEntity.Grade.PLATINUM -> Sponsor.Grade.PLATINUM
SponsorEntity.Grade.GOLD -> Sponsor.Grade.GOLD
}
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.droidknights.app2023.core.domain.model

data class Sponsor(
val name: String,
val imageUrl: String,
val homepage: String,
val grade: Grade,
) {
enum class Grade { PLATINUM, GOLD, }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.droidknights.app2023.core.domain.usecase

import com.droidknights.app2023.core.data.repository.SponsorRepository
import com.droidknights.app2023.core.domain.mapper.toDomain
import com.droidknights.app2023.core.domain.model.Sponsor
import javax.inject.Inject

class GetSponsorsUseCase @Inject constructor(
private val sponsorRepository: SponsorRepository,
) {

suspend operator fun invoke(): List<Sponsor> {
return sponsorRepository.getSponsors().map { it.toDomain() }
}
}