Skip to content

Commit

Permalink
Create cloud data source for location (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
yuriisurzhykov authored May 26, 2024
2 parents def06bb + e1b789e commit 4850343
Show file tree
Hide file tree
Showing 60 changed files with 519 additions and 162 deletions.
1 change: 1 addition & 0 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ java {

dependencies {
implementation(libs.kotlinx.coroutines.core)
implementation(libs.retrofit)
}
File renamed without changes.
11 changes: 6 additions & 5 deletions data/cloud/build.gradle.kts → core/data/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
plugins {
alias(libs.plugins.jetbrains.kotlin.android)
alias(libs.plugins.android.library)
alias(libs.plugins.jetbrains.kotlin.android)
alias(libs.plugins.kotlin.serialization)
}

android {
namespace = "com.github.yuriisurzhykov.purs.data.cloud"
namespace = "com.github.yuriisurzhykov.purs.core.data"
compileSdk = ProjectProperties.compileSdkVersion

defaultConfig {
Expand Down Expand Up @@ -33,9 +34,9 @@ android {
}

dependencies {
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.serialization.json)
implementation(libs.retrofit)
implementation(libs.okhttp)
implementation(libs.okhttp.logging.interceptor)
implementation(libs.kotlinx.serialization.json)
implementation(libs.retrofit.converter.kotlinx.serialization)
implementation(libs.javax.inject)
}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.github.yuriisurzhykov.purs.core.data

interface CloudDataSource {

suspend fun <T> handle(block: suspend () -> T): T

abstract class Abstract(
private val handleError: HandleError
) : CloudDataSource {
override suspend fun <T> handle(block: suspend () -> T): T {
return try {
block.invoke()
} catch (error: Exception) {
throw handleError.handle(error)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.github.yuriisurzhykov.purs.core.data

interface HandleError {

fun handle(exception: Exception): Exception
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.github.yuriisurzhykov.purs.core.data

import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaType
import retrofit2.Converter

interface ProvideConverterFactory {

fun converterFactory(): Converter.Factory

abstract class Abstract(
private val mediaType: MediaType = "application/json; charset=UTF8".toMediaType()
) : ProvideConverterFactory {
override fun converterFactory(): Converter.Factory {
return Json.asConverterFactory(mediaType)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.github.yuriisurzhykov.purs.core.data

import okhttp3.logging.HttpLoggingInterceptor

interface ProvideInterceptor {

fun interceptor(): HttpLoggingInterceptor

abstract class Abstract(
private val loggingLevel: HttpLoggingInterceptor.Level
) : ProvideInterceptor {
override fun interceptor() = HttpLoggingInterceptor().apply {
level = loggingLevel
}
}

class Debug : Abstract(HttpLoggingInterceptor.Level.BODY)
class Release : Abstract(HttpLoggingInterceptor.Level.NONE)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.github.yuriisurzhykov.purs.core.data

import okhttp3.OkHttpClient
import java.util.concurrent.TimeUnit

interface ProvideOkHttpClientBuilder {

fun provideOkHttpClientBuilder(): OkHttpClient.Builder

abstract class Abstract(
private val provideInterceptor: ProvideInterceptor,
private val timeoutSeconds: Long = 60L
) : ProvideOkHttpClientBuilder {
override fun provideOkHttpClientBuilder() = OkHttpClient.Builder()
.addInterceptor(provideInterceptor.interceptor())
.connectTimeout(timeoutSeconds, TimeUnit.SECONDS)
.readTimeout(timeoutSeconds, TimeUnit.SECONDS)
}

class Base(provideInterceptor: ProvideInterceptor) : Abstract(provideInterceptor)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.github.yuriisurzhykov.purs.core.data

import retrofit2.Retrofit

interface ProvideRetrofitBuilder {

fun provideRetrofitBuilder(): Retrofit.Builder

abstract class Abstract(
private val provideConverterFactory: ProvideConverterFactory,
private val httpClientBuilder: ProvideOkHttpClientBuilder
) : ProvideRetrofitBuilder {
override fun provideRetrofitBuilder(): Retrofit.Builder = Retrofit.Builder()
.addConverterFactory(provideConverterFactory.converterFactory())
.client(httpClientBuilder.provideOkHttpClientBuilder().build())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.github.yuriisurzhykov.purs.core

interface MergeStrategy<E> {
fun merge(right: E, left: E): E
}

internal class RequestResponseMergeStrategy<T : Any> : MergeStrategy<RequestResult<T>> {
override fun merge(
right: RequestResult<T>,
left: RequestResult<T>
): RequestResult<T> {
return when {
right is RequestResult.InProgress && left is RequestResult.InProgress -> merge(
right,
left
)

right is RequestResult.Success && left is RequestResult.InProgress -> merge(right, left)
right is RequestResult.InProgress && left is RequestResult.Success -> merge(right, left)
right is RequestResult.Success && left is RequestResult.Success -> merge(right, left)
right is RequestResult.Success && left is RequestResult.Error -> merge(right, left)
right is RequestResult.InProgress && left is RequestResult.Error -> merge(right, left)
right is RequestResult.Error && left is RequestResult.InProgress -> merge(right, left)
right is RequestResult.Error && left is RequestResult.Success -> merge(right, left)

else -> error("Unimplemented branch right=$right & left=$left")
}
}

private fun merge(
cache: RequestResult.InProgress<T>,
server: RequestResult.InProgress<T>
): RequestResult<T> {
return when {
server.data != null -> RequestResult.InProgress(server.data)
else -> RequestResult.InProgress(cache.data)
}
}

@Suppress("UNUSED_PARAMETER")
private fun merge(
cache: RequestResult.Success<T>,
server: RequestResult.InProgress<T>
): RequestResult<T> {
return RequestResult.InProgress(cache.data)
}

@Suppress("UNUSED_PARAMETER")
private fun merge(
cache: RequestResult.InProgress<T>,
server: RequestResult.Success<T>
): RequestResult<T> {
return RequestResult.InProgress(server.data)
}

private fun merge(
cache: RequestResult.Success<T>,
server: RequestResult.Error<T>
): RequestResult<T> {
return RequestResult.Error(data = cache.data, error = server.error)
}

@Suppress("UNUSED_PARAMETER")
private fun merge(
cache: RequestResult.Success<T>,
server: RequestResult.Success<T>
): RequestResult<T> {
return RequestResult.Success(data = server.data)
}

private fun merge(
cache: RequestResult.InProgress<T>,
server: RequestResult.Error<T>
): RequestResult<T> {
return RequestResult.Error(data = server.data ?: cache.data, error = server.error)
}

@Suppress("UNUSED_PARAMETER")
private fun merge(
cache: RequestResult.Error<T>,
server: RequestResult.InProgress<T>
): RequestResult<T> {
return server
}

@Suppress("UNUSED_PARAMETER")
private fun merge(
cache: RequestResult.Error<T>,
server: RequestResult.Success<T>
): RequestResult<T> {
return server
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.github.yuriisurzhykov.purs.core

sealed class RequestResult<out E : Any>(open val data: E? = null) {
data class InProgress<E : Any>(override val data: E? = null) : RequestResult<E>(data)

data class Success<E : Any>(override val data: E) : RequestResult<E>(data)

data class Error<E : Any>(override val data: E? = null, val error: Throwable? = null) :
RequestResult<E>(data)
}

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))
is RequestResult.InProgress -> RequestResult.InProgress(data?.let(mapper))
}
}

internal fun <T : Any> Result<T>.toRequestResult(): RequestResult<T> {
return when {
isSuccess -> RequestResult.Success(getOrThrow())
isFailure -> RequestResult.Error(data = null, error = exceptionOrNull())
else -> error("Impossible branch")
}
}

This file was deleted.

4 changes: 0 additions & 4 deletions data/repository/src/main/AndroidManifest.xml

This file was deleted.

4 changes: 0 additions & 4 deletions domain/src/main/AndroidManifest.xml

This file was deleted.

4 changes: 0 additions & 4 deletions features/location-details/src/main/AndroidManifest.xml

This file was deleted.

71 changes: 0 additions & 71 deletions features/location-selection/build.gradle.kts

This file was deleted.

This file was deleted.

4 changes: 0 additions & 4 deletions features/location-selection/src/main/AndroidManifest.xml

This file was deleted.

Loading

0 comments on commit 4850343

Please sign in to comment.