Skip to content

Commit

Permalink
Create repository for locaiton data sources
Browse files Browse the repository at this point in the history
Signed-off-by: Yurii Surzhykov <yuriisurzhykov@gmail.com>
  • Loading branch information
yuriisurzhykov committed May 27, 2024
1 parent e06b9c2 commit fcc3366
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ sealed class RequestResult<out E : Any>(open val data: E? = null) {
RequestResult<E>(data)
}

fun <I : Any, O : Any> RequestResult<I>.map(mapper: (I) -> O): RequestResult<O> {
inline fun <I : Any, O : Any> RequestResult<I>.map(mapper: (I) -> O): RequestResult<O> {
return when (this) {
is RequestResult.Success -> RequestResult.Success(mapper(data))
is RequestResult.Error -> RequestResult.Error(data?.let(mapper))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ interface LocationCacheDataSource {
}

override suspend fun persistLocation(location: LocationWithWorkingHours) {
locationDao.insert(location)
val newLocation = location.location.copy(locationId = getLocationId.locationId())
locationDao.insert(location.copy(location = newLocation))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ data class WorkingHourCache(
val workingHourId: Long,
val workingHourStart: String,
val workingHourEnd: String,
val workingDayName: String,
val locationId: Long
)
3 changes: 3 additions & 0 deletions location-data/repository/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,13 @@ dependencies {

api(projects.locationData.cloud)
api(projects.locationData.cache)
api(projects.core)
api(projects.core.data)

implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.javax.inject)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.github.yuriisurzhykov.purs.data.repository

import com.github.yuriisurzhykov.purs.core.Mapper
import com.github.yuriisurzhykov.purs.data.cache.GetLocationId
import com.github.yuriisurzhykov.purs.data.cache.model.LocationCache
import com.github.yuriisurzhykov.purs.data.cache.model.LocationWithWorkingHours
import com.github.yuriisurzhykov.purs.data.cache.model.WorkingHourCache
import com.github.yuriisurzhykov.purs.data.cloud.model.LocationCloud
import com.github.yuriisurzhykov.purs.data.cloud.model.WorkingHourCloud
import javax.inject.Inject

interface LocationCloudToCacheMapper : Mapper<LocationCloud, LocationWithWorkingHours> {

class Base @Inject constructor(
private val cloudMapper: LocationCloudMapper,
private val workingHoursCloudMapper: LocationWorkingHoursCloudMapper
) : LocationCloudToCacheMapper {
override fun map(source: LocationCloud): LocationWithWorkingHours {
val sourceLocation: LocationCache = source.map(cloudMapper)
val workingHours: List<WorkingHourCache> = source.map(workingHoursCloudMapper)
return LocationWithWorkingHours(sourceLocation, workingHours)
}
}
}

class LocationCloudMapper @Inject constructor(
private val getLocationId: GetLocationId
) : LocationCloud.Mapper<LocationCache> {
override fun map(locationName: String, workingHours: List<WorkingHourCloud>) =
LocationCache(getLocationId.locationId(), locationName)
}

class LocationWorkingHoursCloudMapper @Inject constructor(
private val mapper: WorkingHoursCloudMapper
) : LocationCloud.Mapper<List<WorkingHourCache>> {
override fun map(
locationName: String,
workingHours: List<WorkingHourCloud>
): List<WorkingHourCache> =
workingHours.map { workingHoursCloud -> workingHoursCloud.map(mapper) }
}

class WorkingHoursCloudMapper @Inject constructor() : WorkingHourCloud.Mapper<WorkingHourCache> {
override fun map(dayName: String, startTime: String, endTime: String): WorkingHourCache {
return WorkingHourCache(0, startTime, endTime, dayName, 0)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.github.yuriisurzhykov.purs.data.repository

import com.github.yuriisurzhykov.purs.core.MergeStrategy
import com.github.yuriisurzhykov.purs.core.RequestResult
import com.github.yuriisurzhykov.purs.core.map
import com.github.yuriisurzhykov.purs.data.cache.LocationCacheDataSource
import com.github.yuriisurzhykov.purs.data.cache.model.LocationWithWorkingHours
import com.github.yuriisurzhykov.purs.data.cloud.LocationCloudDataSource
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
import javax.inject.Inject

interface LocationRepository {

suspend fun fetchLocationDetails(): Flow<RequestResult<LocationWithWorkingHours>>

class Base @Inject constructor(
private val cloudDataSource: LocationCloudDataSource,
private val cacheDataSource: LocationCacheDataSource,
private val sourceMergeStrategy: MergeStrategy<RequestResult<LocationWithWorkingHours>>,
private val mapper: LocationCloudToCacheMapper
) : LocationRepository {
override suspend fun fetchLocationDetails(): Flow<RequestResult<LocationWithWorkingHours>> {
// Fetch cached data if any
val cachedResponse = cacheDataSource.fetchLocation()
// Start loading data from cloud
val cloudResponse = cloudDataSource.fetchLocation()
.map { response -> // Map cloud data to cache data
response.map { it.let { locationCloud -> mapper.map(locationCloud) } }
}.onEach { response -> // Persist cloud data to cache
response.map { cacheDataSource.persistLocation(it) }
}

// Produce initial state that is loading
val initial =
flowOf<RequestResult<LocationWithWorkingHours>>(RequestResult.InProgress())

// Combine two data sources together with the strategy based on cloud and cache results
val combinedSources = cachedResponse.combine(cloudResponse) { cache, cloud ->
sourceMergeStrategy.merge(cache, cloud)
}
return merge(initial, combinedSources)
}
}
}

0 comments on commit fcc3366

Please sign in to comment.