diff --git a/core/src/main/java/com/github/yuriisurzhykov/purs/core/RequestResult.kt b/core/src/main/java/com/github/yuriisurzhykov/purs/core/RequestResult.kt index df67d30..68e7774 100644 --- a/core/src/main/java/com/github/yuriisurzhykov/purs/core/RequestResult.kt +++ b/core/src/main/java/com/github/yuriisurzhykov/purs/core/RequestResult.kt @@ -9,7 +9,7 @@ sealed class RequestResult(open val data: E? = null) { RequestResult(data) } -fun RequestResult.map(mapper: (I) -> O): RequestResult { +inline fun RequestResult.map(mapper: (I) -> O): RequestResult { return when (this) { is RequestResult.Success -> RequestResult.Success(mapper(data)) is RequestResult.Error -> RequestResult.Error(data?.let(mapper)) diff --git a/location-data/cache/src/main/java/com/github/yuriisurzhykov/purs/data/cache/LocationCacheDataSource.kt b/location-data/cache/src/main/java/com/github/yuriisurzhykov/purs/data/cache/LocationCacheDataSource.kt index c5ef367..1f3fcad 100644 --- a/location-data/cache/src/main/java/com/github/yuriisurzhykov/purs/data/cache/LocationCacheDataSource.kt +++ b/location-data/cache/src/main/java/com/github/yuriisurzhykov/purs/data/cache/LocationCacheDataSource.kt @@ -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)) } } } \ No newline at end of file diff --git a/location-data/cache/src/main/java/com/github/yuriisurzhykov/purs/data/cache/model/WorkingHourCache.kt b/location-data/cache/src/main/java/com/github/yuriisurzhykov/purs/data/cache/model/WorkingHourCache.kt index c76d35e..bcac8f1 100644 --- a/location-data/cache/src/main/java/com/github/yuriisurzhykov/purs/data/cache/model/WorkingHourCache.kt +++ b/location-data/cache/src/main/java/com/github/yuriisurzhykov/purs/data/cache/model/WorkingHourCache.kt @@ -19,5 +19,6 @@ data class WorkingHourCache( val workingHourId: Long, val workingHourStart: String, val workingHourEnd: String, + val workingDayName: String, val locationId: Long ) \ No newline at end of file diff --git a/location-data/repository/build.gradle.kts b/location-data/repository/build.gradle.kts index beeee5e..8403ada 100644 --- a/location-data/repository/build.gradle.kts +++ b/location-data/repository/build.gradle.kts @@ -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) diff --git a/location-data/repository/src/main/java/com/github/yuriisurzhykov/purs/data/repository/LocationCloudMappers.kt b/location-data/repository/src/main/java/com/github/yuriisurzhykov/purs/data/repository/LocationCloudMappers.kt new file mode 100644 index 0000000..6a971e0 --- /dev/null +++ b/location-data/repository/src/main/java/com/github/yuriisurzhykov/purs/data/repository/LocationCloudMappers.kt @@ -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 { + + 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 = source.map(workingHoursCloudMapper) + return LocationWithWorkingHours(sourceLocation, workingHours) + } + } +} + +class LocationCloudMapper @Inject constructor( + private val getLocationId: GetLocationId +) : LocationCloud.Mapper { + override fun map(locationName: String, workingHours: List) = + LocationCache(getLocationId.locationId(), locationName) +} + +class LocationWorkingHoursCloudMapper @Inject constructor( + private val mapper: WorkingHoursCloudMapper +) : LocationCloud.Mapper> { + override fun map( + locationName: String, + workingHours: List + ): List = + workingHours.map { workingHoursCloud -> workingHoursCloud.map(mapper) } +} + +class WorkingHoursCloudMapper @Inject constructor() : WorkingHourCloud.Mapper { + override fun map(dayName: String, startTime: String, endTime: String): WorkingHourCache { + return WorkingHourCache(0, startTime, endTime, dayName, 0) + } +} \ No newline at end of file diff --git a/location-data/repository/src/main/java/com/github/yuriisurzhykov/purs/data/repository/LocationRepository.kt b/location-data/repository/src/main/java/com/github/yuriisurzhykov/purs/data/repository/LocationRepository.kt new file mode 100644 index 0000000..58a017d --- /dev/null +++ b/location-data/repository/src/main/java/com/github/yuriisurzhykov/purs/data/repository/LocationRepository.kt @@ -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> + + class Base @Inject constructor( + private val cloudDataSource: LocationCloudDataSource, + private val cacheDataSource: LocationCacheDataSource, + private val sourceMergeStrategy: MergeStrategy>, + private val mapper: LocationCloudToCacheMapper + ) : LocationRepository { + override suspend fun fetchLocationDetails(): Flow> { + // 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.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) + } + } +} \ No newline at end of file