Skip to content

Commit

Permalink
App open weather api and models to service layer
Browse files Browse the repository at this point in the history
  • Loading branch information
shounakmulay committed May 25, 2022
1 parent 897b1e8 commit 5c1ccba
Show file tree
Hide file tree
Showing 19 changed files with 210 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ package com.wednesday.template.domain.weather
data class City(
val id: Int,
val title: String,
val locationType: String,
val country: String,
val latitude: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ import com.wednesday.template.domain.weather.City
val city = City(
id = 1,
title = "title 1",
locationType = "location 1",
country = "location 1",
latitude = "lat 1"
)
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ class UICityMapperImpl : UICityMapper {
return UICity(
cityId = from1.id,
title = from1.title,
locationType = from1.locationType,
locationType = from1.country,
displayTitle = UIText { block(from1.title) },
displayLocationType = UIText { block(from1.locationType) },
displayLocationType = UIText { block(from1.country) },
latitude = from1.latitude,
isFavourite = from2
)
Expand All @@ -35,7 +35,7 @@ class UICityMapperImpl : UICityMapper {
return City(
id = from.cityId,
title = from.title,
locationType = from.locationType,
country = from.locationType,
latitude = from.latitude
)
}
Expand All @@ -45,9 +45,9 @@ class UICityMapperImpl : UICityMapper {
return UICity(
cityId = from.id,
title = from.title,
locationType = from.locationType,
locationType = from.country,
displayTitle = UIText { block(from.title) },
displayLocationType = UIText { block(from.locationType) },
displayLocationType = UIText { block(from.country) },
latitude = from.latitude,
isFavourite = true
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import com.wednesday.template.presentation.weather.UICity
val city = City(
id = 1,
title = "title 1",
locationType = "location 1",
country = "location 1",
latitude = "lat 1"
)

val uiCity = UICity(
cityId = city.id,
title = city.title,
displayTitle = UIText { block(city.title) },
locationType = city.locationType,
displayLocationType = UIText { block(city.locationType) },
locationType = city.country,
displayLocationType = UIText { block(city.country) },
latitude = city.latitude,
isFavourite = false
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,34 @@ package com.wednesday.template.repo.weather

import com.wednesday.template.domain.weather.City
import com.wednesday.template.repo.util.Mapper
import com.wednesday.template.service.weather.LocalCity
import com.wednesday.template.service.weather.RemoteCity
import com.wednesday.template.service.openWeather.geoCoding.LocalLocation
import com.wednesday.template.service.openWeather.geoCoding.RemoteLocation
import timber.log.Timber

interface DomainCityMapper : Mapper<LocalCity, City> {
fun mapRemoteCity(from: RemoteCity): City
fun mapRemoteCity(from: List<RemoteCity>): List<City> = from.map(::mapRemoteCity)
interface DomainCityMapper : Mapper<LocalLocation, City> {
fun mapRemoteCity(from: RemoteLocation): City
fun mapRemoteCity(from: List<RemoteLocation>): List<City> = from.map(::mapRemoteCity)
}

class DomainCityMapperImpl : DomainCityMapper {

override fun mapRemoteCity(from: RemoteCity): City {
override fun mapRemoteCity(from: RemoteLocation): City {
Timber.tag(TAG).d("mapRemoteCity: from = $from")
return City(
id = from.woeid,
title = from.title,
locationType = from.locationType,
latitude = from.latitude
id = (from.lat + from.lon).toInt(),
title = from.name,
country = from.country,
latitude = "${from.lat} ${from.lon}"
)
}

override fun map(from: LocalCity): City {
override fun map(from: LocalLocation): City {
Timber.tag(TAG).d("map: from = $from")
return City(
id = from.woeid,
title = from.title,
locationType = from.locationType,
latitude = from.latitude
id = (from.lat + from.lon).toInt(),
title = from.name,
country = from.country,
latitude = "${from.lat} ${from.lon}"
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@ package com.wednesday.template.repo.weather

import com.wednesday.template.domain.weather.City
import com.wednesday.template.repo.util.Mapper
import com.wednesday.template.service.weather.LocalCity
import com.wednesday.template.service.openWeather.geoCoding.LocalLocation
import timber.log.Timber

interface LocalCityMapper : Mapper<City, LocalCity>
interface LocalCityMapper : Mapper<City, LocalLocation>

class LocalCityMapperImpl : LocalCityMapper {

override fun map(from: City): LocalCity {
override fun map(from: City): LocalLocation {
Timber.tag(TAG).d("map: from = $from")
return LocalCity(
woeid = from.id,
title = from.title,
locationType = from.locationType,
latitude = from.latitude
val (lat, lon) = from.latitude.split(" ")
return LocalLocation(
country = from.country,
name = from.title,
lat = lat.toDouble(),
lon = lon.toDouble(),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@ package com.wednesday.template.repo.weather
import com.wednesday.template.domain.weather.City
import com.wednesday.template.domain.weather.Weather
import com.wednesday.template.repo.date.DateRepo
import com.wednesday.template.service.weather.WeatherLocalService
import com.wednesday.template.service.weather.WeatherRemoteService
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import com.wednesday.template.service.weather.OpenWeatherLocalService
import com.wednesday.template.service.weather.OpenWeatherRemoteService
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import timber.log.Timber

class WeatherRepositoryImpl(
private val weatherRemoteService: WeatherRemoteService,
private val weatherLocalService: WeatherLocalService,
private val weatherRemoteService: OpenWeatherRemoteService,
private val weatherLocalService: OpenWeatherLocalService,
private val domainCityMapper: DomainCityMapper,
private val localCityMapper: LocalCityMapper,
private val localWeatherMapper: LocalWeatherMapper,
Expand All @@ -26,7 +25,7 @@ class WeatherRepositoryImpl(

override suspend fun searchCities(searchTerm: String): List<City> {
Timber.tag(TAG).d("searchCities: searchTerm = $searchTerm")
return weatherRemoteService.searchCities(searchTerm)
return weatherRemoteService.geocodingSearch(searchTerm)
.let { domainCityMapper.mapRemoteCity(it) }
}

Expand Down Expand Up @@ -55,39 +54,41 @@ class WeatherRepositoryImpl(

override suspend fun fetchWeatherForFavouriteCities(): Unit = coroutineScope {
Timber.tag(TAG).d("fetchWeatherForFavouriteCities() called")
val todayDate = dateRepo.todayDate()
weatherLocalService.getFavoriteCities().map {
async {
val dayWeatherList = weatherLocalService.getLocalDayWeather(woeid = it.woeid)
val isWeatherListStale =
dayWeatherList.find { dateRepo.mapDate(it.date) == todayDate } == null

if (dayWeatherList.isEmpty() || isWeatherListStale) {
val remoteWeather = weatherRemoteService.weatherForCity(it.woeid)

weatherLocalService.deleteCurrentAndAddNewWeatherData(
woeid = it.woeid,
weather = localWeatherMapper.map(remoteWeather, it.woeid),
weatherList = localDayWeatherMapper.map(remoteWeather, it.woeid)
)
}
}
}.awaitAll()
// val todayDate = dateRepo.todayDate()
// weatherLocalService.getFavoriteCities().map {
// async {
// val dayWeatherList = weatherLocalService.getLocalDayWeather(woeid = it.woeid)
// val isWeatherListStale =
// dayWeatherList.find { dateRepo.mapDate(it.date) == todayDate } == null
//
// if (dayWeatherList.isEmpty() || isWeatherListStale) {
// val remoteWeather = weatherRemoteService.weatherForCity(it.woeid)
//
// weatherLocalService.deleteCurrentAndAddNewWeatherData(
// woeid = it.woeid,
// weather = localWeatherMapper.map(remoteWeather, it.woeid),
// weatherList = localDayWeatherMapper.map(remoteWeather, it.woeid)
// )
// }
// }
// }.awaitAll()
}

override suspend fun getFavouriteCitiesWeatherList(): List<Weather> {
Timber.tag(TAG).d("getFavouriteCitiesWeatherList() called")
return weatherLocalService
.getFavouriteCitiesWeatherList()
.let(domainWeatherMapper::map)
// return weatherLocalService
// .getFavouriteCitiesWeatherList()
// .let(domainWeatherMapper::map)
return listOf()
}

override fun getFavouriteCitiesWeatherFlow(): Flow<List<Weather>> {
Timber.tag(TAG).d("getFavouriteCitiesWeatherFlow() called")
return weatherLocalService
.getFavouriteCitiesWeatherFlow()
.map { domainWeatherMapper.map(it) }
.onEach { Timber.tag(TAG).d("getFavouriteCitiesWeatherFlow: emit = $it") }
// return weatherLocalService
// .getFavouriteCitiesWeatherFlow()
// .map { domainWeatherMapper.map(it) }
// .onEach { Timber.tag(TAG).d("getFavouriteCitiesWeatherFlow: emit = $it") }
return flowOf()
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import com.wednesday.template.domain.weather.City
val cityMappedFromLocalCity = City(
id = localCity.woeid,
title = localCity.title,
locationType = localCity.locationType,
country = localCity.locationType,
latitude = localCity.latitude
)

val cityMappedFromRemoteCity = City(
id = remoteCity.woeid,
title = remoteCity.title,
locationType = remoteCity.locationType,
country = remoteCity.locationType,
latitude = remoteCity.latitude
)
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
package com.wednesday.template.service

import com.wednesday.template.service.base.getRetrofit
import com.wednesday.template.service.base.getOpenWeatherRetrofit
import com.wednesday.template.service.base.getRoomDatabase
import com.wednesday.template.service.openWeather.OpenWeatherLocalServiceImpl
import com.wednesday.template.service.room.AndroidTemplateDatabase
import com.wednesday.template.service.weather.WeatherLocalService
import com.wednesday.template.service.weather.WeatherLocalServiceImpl
import com.wednesday.template.service.weather.WeatherRemoteService
import com.wednesday.template.service.weather.OpenWeatherLocalService
import com.wednesday.template.service.weather.OpenWeatherRemoteService
import org.koin.dsl.module
import retrofit2.Retrofit

val serviceModule = module {

// Retrofit
single { getRetrofit(get()) }
single { getOpenWeatherRetrofit(get()) }

// Room
single { getRoomDatabase(get()) }

// Weather
single { getWeatherRemoteService(get()) }
single<WeatherLocalService> { getWeatherLocalService(get()) }
single<OpenWeatherLocalService> { getWeatherLocalService(get()) }

// OpenWeather
}

fun getWeatherLocalService(database: AndroidTemplateDatabase): WeatherLocalServiceImpl {
fun getWeatherLocalService(database: AndroidTemplateDatabase): OpenWeatherLocalServiceImpl {
return database.databaseDao()
}

fun getWeatherRemoteService(retrofit: Retrofit): WeatherRemoteService {
return retrofit.create(WeatherRemoteService::class.java)
fun getWeatherRemoteService(retrofit: Retrofit): OpenWeatherRemoteService {
return retrofit.create(OpenWeatherRemoteService::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.wednesday.template.service.openWeather.geoCoding

import androidx.room.Entity

@Entity(tableName = "favorite_locations", primaryKeys = ["lat", "lon"])
data class LocalLocation(
val country: String,
val lat: Double,
val lon: Double,
val name: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.wednesday.template.service.openWeather.geoCoding


import androidx.annotation.Keep
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Keep
@Serializable
data class RemoteLocation(
@SerialName("country")
val country: String,
@SerialName("lat")
val lat: Double,
@SerialName("lon")
val lon: Double,
@SerialName("name")
val name: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ package com.wednesday.template.service.base
import android.content.Context
import androidx.room.Room.databaseBuilder
import com.wednesday.template.service.room.AndroidTemplateDatabase
import com.wednesday.template.service.room.MIGRATION_1_2

fun getRoomDatabase(applicationContext: Context): AndroidTemplateDatabase {
return databaseBuilder(
applicationContext,
AndroidTemplateDatabase::class.java,
"android_template_database"
).build()
)
.addMigrations(MIGRATION_1_2)
.build()
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit

@OptIn(ExperimentalSerializationApi::class)
fun getRetrofit(context: Context, vararg interceptors: Interceptor): Retrofit {
fun getOpenWeatherRetrofit(context: Context, vararg interceptors: Interceptor): Retrofit {
val httpLoggingInterceptor = HttpLoggingInterceptor()

httpLoggingInterceptor.level = when (BuildConfig.DEBUG) {
Expand Down Expand Up @@ -41,7 +41,7 @@ fun getRetrofit(context: Context, vararg interceptors: Interceptor): Retrofit {
build()
}

val apiBaseUrl = "https://www.metaweather.com/"
val apiBaseUrl = "http://api.openweathermap.org/"
val contentType = "application/json".toMediaType()
val json = Json {
ignoreUnknownKeys = true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.wednesday.template.service.base.retrofit.interceptors

import okhttp3.Interceptor
import okhttp3.Response

class OpenWeatherApiKeyInterceptor: Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {

}
}
Loading

0 comments on commit 5c1ccba

Please sign in to comment.