Skip to content

Commit

Permalink
4.4.0 (#54)
Browse files Browse the repository at this point in the history
* adding comments

* Updating type conversion for Layers and DynamicConfigs

* comment name changes
  • Loading branch information
daniel-statsig authored Mar 22, 2022
1 parent d27e2ce commit bd0b0ab
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 158 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ dependencies {
implementation 'androidx.core:core-ktx:1.5.0'
implementation 'androidx.appcompat:appcompat:1.2.0'

implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.google.code.gson:gson:2.8.9'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'

testImplementation 'junit:junit:4.12'
Expand Down
75 changes: 25 additions & 50 deletions src/main/java/com/statsig/androidsdk/DynamicConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,7 @@ class DynamicConfig(
* @return the value at the given key, or the default value if not found
*/
fun getString(key: String, default: String?): String? {
if (!this.jsonValue.containsKey(key)) {
return default;
}
return when (this.jsonValue[key]) {
null -> default
is String -> this.jsonValue[key] as String
else -> default
}
Expand All @@ -37,11 +33,7 @@ class DynamicConfig(
* @return the value at the given key, or the default value if not found
*/
fun getBoolean(key: String, default: Boolean): Boolean {
if (!this.jsonValue.containsKey(key)) {
return default;
}
return when (this.jsonValue[key]) {
null -> default
is Boolean -> this.jsonValue[key] as Boolean
else -> default
}
Expand All @@ -54,13 +46,8 @@ class DynamicConfig(
* @return the value at the given key, or the default value if not found
*/
fun getDouble(key: String, default: Double): Double {
if (!this.jsonValue.containsKey(key)) {
return default;
}
return when (this.jsonValue[key]) {
null -> default
is Double -> this.jsonValue[key] as Double
is Int -> this.jsonValue[key] as Double
return when (val value = this.jsonValue[key]) {
is Number -> value.toDouble()
else -> default
}
}
Expand All @@ -72,22 +59,23 @@ class DynamicConfig(
* @return the value at the given key, or the default value if not found
*/
fun getInt(key: String, default: Int): Int {
if (!this.jsonValue.containsKey(key)) {
return default;
}
if (this.jsonValue[key] == null) {
return default
}
if (
this.jsonValue[key] is Double &&
this.jsonValue[key] as Double == Math.floor(this.jsonValue[key] as Double)
) {
return this.jsonValue[key] as Int
return when (val value = this.jsonValue[key]) {
is Number -> value.toInt()
else -> default
}
if (this.jsonValue[key] is Int) {
return this.jsonValue[key] as Int
}

/**
* Gets a value from the config, falling back to the provided default value
* @param key the index within the DynamicConfig to fetch a value from
* @param default the default value to return if the expected key does not exist in the config
* @return the value at the given key, or the default value if not found
*/
fun getLong(key: String, default: Long): Long {
return when (val value = this.jsonValue[key]) {
is Number -> value.toLong()
else -> default
}
return default
}

/**
Expand All @@ -97,15 +85,9 @@ class DynamicConfig(
* @return the value at the given key, or the default value if not found
*/
fun getArray(key: String, default: Array<*>?): Array<*>? {
if (!this.jsonValue.containsKey(key)) {
return default;
}
return when (this.jsonValue[key]) {
null -> default
is Array<*> -> this.jsonValue[key] as Array<*>
is IntArray -> (this.jsonValue[key] as IntArray).toTypedArray()
is DoubleArray -> (this.jsonValue[key] as DoubleArray).toTypedArray()
is BooleanArray -> (this.jsonValue[key] as BooleanArray).toTypedArray()
return when (val value = this.jsonValue[key]) {
is Array<*> -> value
is ArrayList<*> -> value.toTypedArray()
else -> default
}
}
Expand All @@ -117,12 +99,8 @@ class DynamicConfig(
* @return the value at the given key, or the default value if not found
*/
fun getDictionary(key: String, default: Map<String, Any>?): Map<String, Any>? {
if (!this.jsonValue.containsKey(key)) {
return default;
}
return when (this.jsonValue[key]) {
null -> default
is Map<*, *> -> this.jsonValue[key] as Map<String, Any>
return when (val value = this.jsonValue[key]) {
is Map<*, *> -> value as Map<String, Any>
else -> default
}
}
Expand All @@ -133,19 +111,16 @@ class DynamicConfig(
* @return the value at the given key as a DynamicConfig, or null
*/
fun getConfig(key: String): DynamicConfig? {
if (!this.jsonValue.containsKey(key)) {
return null;
}
return when (this.jsonValue[key]) {
null -> null
return when (val value = this.jsonValue[key]) {
is Map<*, *> -> DynamicConfig(
key,
this.jsonValue[key] as Map<String, Any>,
value as Map<String, Any>,
this.rule
)
else -> null
}
}

/**
* Returns a Map representing the JSON object backing this config
* @param key the index within the DynamicConfig to fetch a value from
Expand Down
102 changes: 38 additions & 64 deletions src/main/java/com/statsig/androidsdk/Layer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,133 +14,107 @@ class Layer(
private val allocatedExperimentName: String = "") {

/**
* Gets a value from the config, falling back to the provided default value
* Gets a value from the Layer, falling back to the provided default value
* @param key the index within the Layer to fetch a value from
* @param default the default value to return if the expected key does not exist in the config
* @param default the default value to return if the expected key does not exist in the Layer
* @return the value at the given key, or the default value if not found
*/
fun getString(key: String, default: String?): String? {
if (!this.jsonValue.containsKey(key)) {
return default;
}
return when (this.jsonValue[key]) {
null -> default
is String -> this.jsonValue[key] as String
else -> default
}
}

/**
* Gets a value from the config, falling back to the provided default value
* Gets a value from the Layer, falling back to the provided default value
* @param key the index within the Layer to fetch a value from
* @param default the default value to return if the expected key does not exist in the config
* @param default the default value to return if the expected key does not exist in the Layer
* @return the value at the given key, or the default value if not found
*/
fun getBoolean(key: String, default: Boolean): Boolean {
if (!this.jsonValue.containsKey(key)) {
return default;
}
return when (this.jsonValue[key]) {
null -> default
is Boolean -> this.jsonValue[key] as Boolean
else -> default
}
}

/**
* Gets a value from the config, falling back to the provided default value
* Gets a value from the Layer, falling back to the provided default value
* @param key the index within the Layer to fetch a value from
* @param default the default value to return if the expected key does not exist in the config
* @param default the default value to return if the expected key does not exist in the Layer
* @return the value at the given key, or the default value if not found
*/
fun getDouble(key: String, default: Double): Double {
if (!this.jsonValue.containsKey(key)) {
return default;
}
return when (this.jsonValue[key]) {
null -> default
is Double -> this.jsonValue[key] as Double
is Int -> this.jsonValue[key] as Double
return when (val value = this.jsonValue[key]) {
is Number -> value.toDouble()
else -> default
}
}

/**
* Gets a value from the config, falling back to the provided default value
* Gets a value from the Layer, falling back to the provided default value
* @param key the index within the Layer to fetch a value from
* @param default the default value to return if the expected key does not exist in the config
* @param default the default value to return if the expected key does not exist in the Layer
* @return the value at the given key, or the default value if not found
*/
fun getInt(key: String, default: Int): Int {
if (!this.jsonValue.containsKey(key)) {
return default;
}
if (this.jsonValue[key] == null) {
return default
}
if (
this.jsonValue[key] is Double &&
this.jsonValue[key] as Double == Math.floor(this.jsonValue[key] as Double)
) {
return this.jsonValue[key] as Int
return when (val value = this.jsonValue[key]) {
is Number -> value.toInt()
else -> default
}
if (this.jsonValue[key] is Int) {
return this.jsonValue[key] as Int
}

/**
* Gets a value from the Layer, falling back to the provided default value
* @param key the index within the Layer to fetch a value from
* @param default the default value to return if the expected key does not exist in the Layer
* @return the value at the given key, or the default value if not found
*/
fun getLong(key: String, default: Long): Long {
return when (val value = this.jsonValue[key]) {
is Number -> value.toLong()
else -> default
}
return default
}

/**
* Gets a value from the config, falling back to the provided default value
* Gets a value from the Layer, falling back to the provided default value
* @param key the index within the Layer to fetch a value from
* @param default the default value to return if the expected key does not exist in the config
* @param default the default value to return if the expected key does not exist in the Layer
* @return the value at the given key, or the default value if not found
*/
fun getArray(key: String, default: Array<*>?): Array<*>? {
if (!this.jsonValue.containsKey(key)) {
return default;
}
return when (this.jsonValue[key]) {
null -> default
is Array<*> -> this.jsonValue[key] as Array<*>
is IntArray -> (this.jsonValue[key] as IntArray).toTypedArray()
is DoubleArray -> (this.jsonValue[key] as DoubleArray).toTypedArray()
is BooleanArray -> (this.jsonValue[key] as BooleanArray).toTypedArray()
return when (val value = this.jsonValue[key]) {
is Array<*> -> value
is ArrayList<*> -> value.toTypedArray()
else -> default
}
}

/**
* Gets a dictionary from the config, falling back to the provided default value
* Gets a dictionary from the Layer, falling back to the provided default value
* @param key the index within the Layer to fetch a dictionary from
* @param default the default value to return if the expected key does not exist in the config
* @param default the default value to return if the expected key does not exist in the Layer
* @return the value at the given key, or the default value if not found
*/
fun getDictionary(key: String, default: Map<String, Any>?): Map<String, Any>? {
if (!this.jsonValue.containsKey(key)) {
return default;
}
return when (this.jsonValue[key]) {
null -> default
is Map<*, *> -> this.jsonValue[key] as Map<String, Any>
return when (val value = this.jsonValue[key]) {
is Map<*, *> -> value as Map<String, Any>
else -> default
}
}

/**
* Gets a value from the config as a new DynamicConfig, or null if not found
* @param key the index within the DynamicConfig to fetch a value from
* Gets a value from the Layer as a DynamicConfig, or null if not found
* @param key the index within the Layer to fetch a value from
* @return the value at the given key as a DynamicConfig, or null
*/
fun getConfig(key: String): DynamicConfig? {
if (!this.jsonValue.containsKey(key)) {
return null;
}
return when (this.jsonValue[key]) {
null -> null
return when (val value = this.jsonValue[key]) {
is Map<*, *> -> DynamicConfig(
key,
this.jsonValue[key] as Map<String, Any>,
value as Map<String, Any>,
this.rule
)
else -> null
Expand Down
20 changes: 15 additions & 5 deletions src/main/java/com/statsig/androidsdk/Statsig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,21 @@ object Statsig {
return client.getExperiment(experimentName, keepDeviceValue)
}

/**
* Check the value of a Layer configured in the Statsig console for the initialized
* user
* @param layerName the name of the Layer to check
* @param keepDeviceValue whether the value returned should be kept for the user on the device for the duration of any active experiments
* @return the current layer values as a Layer object
* @throws IllegalStateException if the SDK has not been initialized
*/
@JvmOverloads
@JvmStatic
fun getLayer(layerName: String, keepDeviceValue: Boolean = false): Layer {
enforceInitialized("getLayer")
return client.getLayer(layerName, keepDeviceValue)
}

/**
* Log an event to Statsig for the current user
* @param eventName the name of the event to track
Expand Down Expand Up @@ -251,11 +266,6 @@ object Statsig {
return client.getStore().getAllOverrides()
}

fun getLayer(layerName: String, keepDeviceValue: Boolean = false): Layer {
enforceInitialized("getLayer")
return client.getLayer(layerName, keepDeviceValue)
}

private fun enforceInitialized(functionName: String) {
client.enforceInitialized(functionName)
}
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/com/statsig/androidsdk/StatsigClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,14 @@ internal class StatsigClient() {
return res
}

/**
* Check the value of an Layer configured in the Statsig console for the initialized
* user
* @param layerName the name of the Layer to check
* @param keepDeviceValue whether the value returned should be kept for the user on the device for the duration of any active experiments
* @return the current layer values as a Layer object
* @throws IllegalStateException if the SDK has not been initialized
*/
fun getLayer(layerName: String, keepDeviceValue: Boolean = false): Layer {
enforceInitialized("getLayer")
val res = store.getLayer(layerName, keepDeviceValue)
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/com/statsig/androidsdk/StatsigNetwork.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.statsig.androidsdk

import android.content.SharedPreferences
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.ToNumberPolicy
import java.net.HttpURLConnection
import java.net.URL
import java.util.concurrent.TimeUnit
Expand Down Expand Up @@ -65,7 +67,7 @@ internal fun StatsigNetwork(): StatsigNetwork = StatsigNetworkImpl()

private class StatsigNetworkImpl : StatsigNetwork {

private val gson = Gson()
private val gson = GsonBuilder().setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE).create()

private var lastSyncTimeForUser: Long = 0
private lateinit var sharedPrefs: SharedPreferences
Expand Down
Loading

0 comments on commit bd0b0ab

Please sign in to comment.