Skip to content

Commit

Permalink
add custom UUID deserializer. Renaming experiments. Upgrade min java sdk
Browse files Browse the repository at this point in the history
  • Loading branch information
Tayfun Oztemel committed Jul 11, 2024
1 parent 6eb7fab commit 7b1c9fc
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 76 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ android {

defaultConfig {
applicationId "com.crobox.sdk.testapp"
minSdk 22
minSdk 26
targetSdk 34
versionCode 1
versionName "1.0"
Expand Down
8 changes: 4 additions & 4 deletions app/src/main/kotlin/com/crobox/sdk/testapp/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,9 @@ class MainActivity : AppCompatActivity() {
val TAG = "PromotionCallback"

override fun onPromotions(response: PromotionsResponse?) {
val experiments: List<String>? =
response?.context?.experiments?.map { experiment ->
"Experiment[Id: ${experiment.id}, Name: ${experiment.name}]"
val campaigns: List<String>? =
response?.context?.campaigns?.map { campaign ->
"Campaign[Id: ${campaign.id}, Name: ${campaign.name}]"
}

Log.d(
Expand All @@ -126,7 +126,7 @@ class MainActivity : AppCompatActivity() {
Context [
VisitorId: ${response?.context?.visitorId}
SessionId: ${response?.context?.sessionId}
Experiments: ${experiments?.joinToString()}
Campaigns: ${campaigns?.joinToString()}
]
""".trimIndent()
)
Expand Down
2 changes: 1 addition & 1 deletion sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ android {
compileSdk 34

defaultConfig {
minSdk 22
minSdk 26
targetSdk 34
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
Expand Down
10 changes: 8 additions & 2 deletions sdk/src/main/kotlin/com/crobox/sdk/data/api/CroboxAPIClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,21 @@ import com.google.gson.Strictness
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.UUID
import java.util.concurrent.TimeUnit

internal object CroboxAPIClient {
val clientWithOutToken: Retrofit
get() {
val client: OkHttpClient = client()

val gson = GsonBuilder().setStrictness(Strictness.LENIENT).disableHtmlEscaping()
.enableComplexMapKeySerialization().create()
val gson =
GsonBuilder()
.setStrictness(Strictness.LENIENT)
.disableHtmlEscaping()
.enableComplexMapKeySerialization()
.registerTypeAdapter(UUID::class.java, CustomUUIDDeserializer())
.create()

return Retrofit.Builder().client(client).baseUrl(Constant.API_URL)
.addConverterFactory(GsonConverterFactory.create(gson)).build()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.crobox.sdk.data.api

import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import java.lang.reflect.Type
import java.nio.ByteBuffer
import java.util.Base64
import java.util.UUID

internal class CustomUUIDDeserializer : JsonDeserializer<UUID> {

override fun deserialize(
json: JsonElement?,
typeOfT: Type?,
context: JsonDeserializationContext?
): UUID {
val uuidEncoded = json?.asString
return uuidEncoded?.let {
if (it.length == 36) {
UUID.fromString(uuidEncoded)
} else {
val bb = ByteBuffer.wrap(Base64.getUrlDecoder().decode(uuidEncoded))
UUID(bb.getLong(), bb.getLong())
}
} ?: UUID.randomUUID()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ package com.crobox.sdk.domain
import com.google.gson.annotations.SerializedName

/**
* Represents an ongoing campaign
* Represents an ongoing Campaign
*
* @property id Campaign ID
* @property name Campaign Name
* @property variantId Id of the Campaign Variant
* @property variantName Name of the Campaign Variant
* @property control Indicates if variant is allocated to the control group
*/
class Experiment {
class Campaign {
@SerializedName("id") val id: String? = null
@SerializedName("name") val name: String? = null
@SerializedName("variantId")val variantId: String? = null
Expand Down
18 changes: 13 additions & 5 deletions sdk/src/main/kotlin/com/crobox/sdk/domain/PromotionContext.kt
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
package com.crobox.sdk.domain

import com.google.gson.annotations.SerializedName
import java.util.UUID

/**
* The context about campaigns
*
* @property experiments The list of ongoing campaigns
* @property campaigns The list of ongoing campaigns
* @property sessionId Session ID
* @property visitorId Visitor ID
* @property groupName List of campaign and variant names, combined
*
*/
class PromotionContext {
@SerializedName("experiments") val experiments: List<Experiment>? = null
@SerializedName("sid") val sessionId: String? = null
@SerializedName("pid") val visitorId: String? = null
@SerializedName("groupName") val groupName: String? = null
@SerializedName("experiments")
val campaigns: List<Campaign>? = null

@SerializedName("sid")
val sessionId: UUID? = null

@SerializedName("pid")
val visitorId: UUID? = null

@SerializedName("groupName")
val groupName: String? = null
}
60 changes: 22 additions & 38 deletions sdk/src/main/kotlin/com/crobox/sdk/presenter/CroboxAPIPresenter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.crobox.sdk.data.model.RequestQueryParams
import com.crobox.sdk.domain.BaseResponse
import com.crobox.sdk.domain.PromotionsResponse
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import retrofit2.Call
import retrofit2.Callback
Expand All @@ -34,15 +35,12 @@ internal class CroboxAPIPresenter(private val config: CroboxConfig) {

val parameters = promotionsQuery(placeholderId, queryParams)
val stringParameters = parameters.mapValues { it.value.toString() }
val body = promotionRequestBody(impressions)

val requestBody = body.toRequestBody("text/plain".toMediaTypeOrNull())
val requestBody = promotionRequestBody(impressions)

apiInterface.promotions(stringParameters, requestBody)
?.enqueue(object : Callback<PromotionsResponse?> {
override fun onResponse(
call: Call<PromotionsResponse?>,
response: Response<PromotionsResponse?>
call: Call<PromotionsResponse?>, response: Response<PromotionsResponse?>
) {
try {
if (response.isSuccessful) {
Expand All @@ -65,19 +63,15 @@ internal class CroboxAPIPresenter(private val config: CroboxConfig) {
}

fun event(
eventType: EventType,
queryParams: RequestQueryParams,
additionalParams: Any?
eventType: EventType, queryParams: RequestQueryParams, additionalParams: Any?
) {

val parameters = eventQuery(queryParams, additionalParams, eventType)
val stringParameters = parameters.mapValues { it.value.toString() }

apiInterface.event(stringParameters)
?.enqueue(object : Callback<BaseResponse?> {
apiInterface.event(stringParameters)?.enqueue(object : Callback<BaseResponse?> {
override fun onResponse(
call: Call<BaseResponse?>,
response: Response<BaseResponse?>
call: Call<BaseResponse?>, response: Response<BaseResponse?>
) {
try {
if (!response.isSuccessful) {
Expand All @@ -95,9 +89,7 @@ internal class CroboxAPIPresenter(private val config: CroboxConfig) {
}

private fun eventQuery(
queryParams: RequestQueryParams,
additionalParams: Any?,
eventType: EventType
queryParams: RequestQueryParams, additionalParams: Any?, eventType: EventType
): Map<String, Any> {

// Mandatory parameters
Expand All @@ -108,36 +100,31 @@ internal class CroboxAPIPresenter(private val config: CroboxConfig) {
when (eventType) {
EventType.Error -> (additionalParams as? ErrorQueryParams)?.let {
errorEvent(
it,
parameters
it, parameters
)
}

EventType.Click -> (additionalParams as? ClickQueryParams)?.let {
clickEvent(
it,
parameters
it, parameters
)
}

EventType.AddCart -> (additionalParams as? CartQueryParams)?.let {
addToCartEvent(
it,
parameters
it, parameters
)
}

EventType.RemoveCart -> (additionalParams as? CartQueryParams)?.let {
removeFromCartEvent(
it,
parameters
it, parameters
)
}

EventType.CustomEvent -> (additionalParams as? CustomQueryParams)?.let {
customEvent(
it,
parameters
it, parameters
)
}

Expand All @@ -152,14 +139,15 @@ internal class CroboxAPIPresenter(private val config: CroboxConfig) {

private fun promotionRequestBody(
impressions: List<String>
): String {
return impressions.indices.zip(impressions)
.joinToString("&") { t -> "${t.first}=${t.second}" }
): RequestBody {
val bodyStr =
impressions.indices.zip(impressions).joinToString("&") { t -> "${t.first}=${t.second}" }

return bodyStr.toRequestBody("text/plain".toMediaTypeOrNull())
}

private fun promotionsQuery(
placeholderId: Int,
queryParams: RequestQueryParams
placeholderId: Int, queryParams: RequestQueryParams
): Map<String, Any> {
val parameters = commonQueryParams(queryParams)
parameters["vpid"] = placeholderId.toString()
Expand Down Expand Up @@ -199,8 +187,7 @@ internal class CroboxAPIPresenter(private val config: CroboxConfig) {
The following arguments are applicable for error events( where t=error ). They are all optional.
*/
private fun errorEvent(
errorQueryParams: ErrorQueryParams,
parameters: MutableMap<String, Any>
errorQueryParams: ErrorQueryParams, parameters: MutableMap<String, Any>
) {
errorQueryParams.tag?.let { parameters["tg"] = it }
errorQueryParams.name?.let { parameters["nm"] = it }
Expand All @@ -226,8 +213,7 @@ internal class CroboxAPIPresenter(private val config: CroboxConfig) {
*/
private fun addToCartEvent(
addCartQueryParams: CartQueryParams,
parameters: MutableMap<String, Any>
addCartQueryParams: CartQueryParams, parameters: MutableMap<String, Any>
) {
addCartQueryParams.productId?.let { parameters["pi"] = it }
addCartQueryParams.price?.let { parameters["price"] = it }
Expand All @@ -240,8 +226,7 @@ internal class CroboxAPIPresenter(private val config: CroboxConfig) {
*/
private fun removeFromCartEvent(
removeFromCartQueryParams: CartQueryParams,
parameters: MutableMap<String, Any>
removeFromCartQueryParams: CartQueryParams, parameters: MutableMap<String, Any>
) {
removeFromCartQueryParams.productId?.let { parameters["pi"] = it }
removeFromCartQueryParams.price?.let { parameters["price"] = it }
Expand All @@ -254,8 +239,7 @@ internal class CroboxAPIPresenter(private val config: CroboxConfig) {
*/
private fun customEvent(
customQueryParams: CustomQueryParams,
parameters: MutableMap<String, Any>
customQueryParams: CustomQueryParams, parameters: MutableMap<String, Any>
) {
customQueryParams.name?.let { parameters["nm"] = it }
customQueryParams.promotionId?.let { parameters["promoId"] = it }
Expand Down
Loading

0 comments on commit 7b1c9fc

Please sign in to comment.