MeilCli/FoodSearch

View on GitHub
features/base/src/main/kotlin/net/meilcli/foodsearch/api/gnavi/adapters/ForeignRestaurantJsonAdapter.kt

Summary

Maintainability
A
0 mins
Test Coverage
package net.meilcli.foodsearch.api.gnavi.adapters

import com.squareup.moshi.*
import net.meilcli.foodsearch.IJsonAdapterFactory
import net.meilcli.foodsearch.api.createNonNullJsonDateException
import net.meilcli.foodsearch.api.gnavi.entities.*
import net.meilcli.foodsearch.extensions.letNullIfEmpty
import java.lang.reflect.Type
import java.util.*
import net.meilcli.foodsearch.api.gnavi.adapters.ForeignRestaurantJsonAdapter_ApiAreaJsonAdapter as ApiAreaJsonAdapter
import net.meilcli.foodsearch.api.gnavi.adapters.ForeignRestaurantJsonAdapter_ApiCategoriesJsonAdapter as ApiCategoriesJsonAdapter
import net.meilcli.foodsearch.api.gnavi.adapters.ForeignRestaurantJsonAdapter_ApiContactJsonAdapter as ApiContactJsonAdapter
import net.meilcli.foodsearch.api.gnavi.adapters.ForeignRestaurantJsonAdapter_ApiForeignRestaurantJsonAdapter as ApiForeignRestaurantJsonAdapter
import net.meilcli.foodsearch.api.gnavi.adapters.ForeignRestaurantJsonAdapter_ApiImageJsonAdapter as ApiImageJsonAdapter
import net.meilcli.foodsearch.api.gnavi.adapters.ForeignRestaurantJsonAdapter_ApiLocationJsonAdapter as ApiLocationJsonAdapter
import net.meilcli.foodsearch.api.gnavi.adapters.ForeignRestaurantJsonAdapter_ApiNameJsonAdapter as ApiNameJsonAdapter

internal class ForeignRestaurantJsonAdapter(moshi: Moshi) : JsonAdapter<ForeignRestaurant>() {

    // https://api.gnavi.co.jp/api/manual/foreignrestsearch/

    private val apiForeignRestaurantJsonAdapter = moshi.adapter(ApiForeignRestaurant::class.java)

    override fun fromJson(reader: JsonReader): ForeignRestaurant? {
        val apiForeignRestaurant = apiForeignRestaurantJsonAdapter.fromJson(reader)
            ?: throw createNonNullJsonDateException(reader)

        val nameOfReading = apiForeignRestaurant.name.nameOfReading ?: apiForeignRestaurant.name.subName ?: ""
        val smallArea = Area(apiForeignRestaurant.location.area.smallAreaName, null)
        val largeCategories = createCategories(apiForeignRestaurant.categories.largeCategoryNames)
        val smallCategories = createCategories(apiForeignRestaurant.categories.smallCategoryNames)
        val contact = Contact(apiForeignRestaurant.contact.address, apiForeignRestaurant.contact.phoneNumber)
        val image = Image(
            apiForeignRestaurant.image.thumbnailUrl.letNullIfEmpty(),
            null,
            apiForeignRestaurant.image.qrCodeUrl.letNullIfEmpty()
        )
        val location = Location(
            longitude = apiForeignRestaurant.location.longitude,
            latitude = apiForeignRestaurant.location.latitude
        )
        val publicRelation = apiForeignRestaurant.publicRelation

        return ForeignRestaurant(
            id = apiForeignRestaurant.id,
            updateAt = apiForeignRestaurant.updateAt,
            name = apiForeignRestaurant.name.name,
            nameOfReading = nameOfReading,
            location = location,
            smallArea = smallArea,
            largeCategories = largeCategories,
            smallCategories = smallCategories,
            url = apiForeignRestaurant.url.letNullIfEmpty(),
            urlForMobile = apiForeignRestaurant.urlForMobile.letNullIfEmpty(),
            couponUrl = null,
            couponUrlForMobile = null,
            image = image,
            openTime = apiForeignRestaurant.openTime,
            holiday = apiForeignRestaurant.holiday,
            access = apiForeignRestaurant.access,
            contact = contact,
            publicRelation = publicRelation,
            averageBudget = apiForeignRestaurant.averageBudget,
            creditCard = apiForeignRestaurant.creditCard.letNullIfEmpty(),
            electronicMoney = null
        )
    }

    private fun createCategories(names: Array<String>): Array<ICategory> {
        return names.asSequence()
            .filter { it.isNotEmpty() }
            .map { Category(it, null) as ICategory }
            .toList()
            .toTypedArray()
    }

    override fun toJson(writer: JsonWriter, value: ForeignRestaurant?) {
        TODO("not implemented")
    }

    internal object InternalJsonAdapterFactory : IJsonAdapterFactory {

        override fun create(type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi): JsonAdapter<*>? {
            return when (type) {
                ApiForeignRestaurant::class.java -> ApiForeignRestaurantJsonAdapter(moshi)
                ApiName::class.java -> ApiNameJsonAdapter(moshi)
                ApiContact::class.java -> ApiContactJsonAdapter(moshi)
                ApiCategories::class.java -> ApiCategoriesJsonAdapter(moshi)
                ApiLocation::class.java -> ApiLocationJsonAdapter(moshi)
                ApiArea::class.java -> ApiAreaJsonAdapter(moshi)
                ApiImage::class.java -> ApiImageJsonAdapter(moshi)
                else -> return null
            }
        }
    }

    @JsonClass(generateAdapter = true)
    internal data class ApiForeignRestaurant(

        val id: String,

        @Json(name = "update_date")
        val updateAt: Date,

        val name: ApiName,

        @Json(name = "business_hour")
        val openTime: String,

        val holiday: String,

        @Json(name = "contacts")
        val contact: ApiContact,

        @Json(name = "sales_points")
        val publicRelation: PublicRelation,

        val access: String,

        @Json(name = "budget")
        val averageBudget: Int,

        @Json(name = "credit_card")
        val creditCard: String,

        val categories: ApiCategories,

        val location: ApiLocation,

        val url: String?,

        @Json(name = "url_mobile")
        val urlForMobile: String?,

        @Json(name = "image_url")
        val image: ApiImage
    )

    @JsonClass(generateAdapter = true)
    internal data class ApiName(

        val name: String,

        @Json(name = "name_sub")
        val subName: String?,

        @Json(name = "name_kana")
        val nameOfReading: String?
    )

    @JsonClass(generateAdapter = true)
    internal data class ApiContact(

        val address: String,

        @Json(name = "tel")
        val phoneNumber: String
    )

    @JsonClass(generateAdapter = true)
    internal data class ApiCategories(

        @Json(name = "category_name_l")
        val largeCategoryNames: Array<String>,

        @Json(name = "category_name_s")
        val smallCategoryNames: Array<String>
    )

    @JsonClass(generateAdapter = true)
    internal data class ApiLocation(

        @Json(name = "latitude_wgs84")
        val latitude: Double,

        @Json(name = "longitude_wgs84")
        val longitude: Double,

        val area: ApiArea
    )

    @JsonClass(generateAdapter = true)
    internal data class ApiArea(

        @Json(name = "areaname_s")
        val smallAreaName: String
    )

    @JsonClass(generateAdapter = true)
    internal data class ApiImage(

        @Json(name = "thumbnail")
        val thumbnailUrl: String?,

        @Json(name = "qrcode")
        val qrCodeUrl: String
    )
}