Skip to content
This repository has been archived by the owner on Jun 1, 2024. It is now read-only.

fix: adjust context evaluation to return correct types #1043

Merged
merged 27 commits into from
Oct 20, 2020
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4505527
refactor: remove deprecated from constructor
uziasferreirazup Sep 28, 2020
1a4077f
Merge branch 'master' of github.com:ZupIT/beagle
uziasferreirazup Sep 29, 2020
dccf069
Merge branch 'master' of github.com:ZupIT/beagle
uziasferreirazup Sep 29, 2020
642ede6
Merge branch 'master' of github.com:ZupIT/beagle
uziasferreirazup Oct 1, 2020
8148100
Merge branch 'master' of github.com:ZupIT/beagle
uziasferreirazup Oct 2, 2020
764080a
Merge branch 'master' of github.com:ZupIT/beagle
uziasferreirazup Oct 2, 2020
720428e
Merge branch 'master' of github.com:ZupIT/beagle
uziasferreirazup Oct 5, 2020
673ab46
Merge branch 'master' of github.com:ZupIT/beagle
uziasferreirazup Oct 5, 2020
248c597
Merge branch 'master' of github.com:ZupIT/beagle
uziasferreirazup Oct 6, 2020
fc478f5
Merge branch 'master' of github.com:ZupIT/beagle
uziasferreirazup Oct 7, 2020
d9d12f3
Merge branch 'master' of github.com:ZupIT/beagle
uziasferreirazup Oct 9, 2020
3328009
Merge branch 'master' of github.com:ZupIT/beagle
uziasferreirazup Oct 9, 2020
bacd5f5
Merge branch 'master' of github.com:ZupIT/beagle
uziasferreirazup Oct 13, 2020
2657086
fix: adjust name action backend
uziasferreirazup Oct 13, 2020
16fed1f
Merge branch 'master' of github.com:ZupIT/beagle
uziasferreirazup Oct 13, 2020
236a947
fix: adjust serialization context
uziasferreirazup Oct 15, 2020
9e85be2
adjust try serializer
uziasferreirazup Oct 16, 2020
d556750
adjust context data manager
uziasferreirazup Oct 16, 2020
bf12c19
adjust try to deserializer
uziasferreirazup Oct 16, 2020
c9ab354
adjust unit tests
uziasferreirazup Oct 17, 2020
cd0959a
adjust class
uziasferreirazup Oct 17, 2020
9ad4ca0
remove space extra
uziasferreirazup Oct 17, 2020
4d8aa40
adjust test in form
uziasferreirazup Oct 17, 2020
20c825d
adjust evaluation
uziasferreirazup Oct 17, 2020
2d579a9
adjust lint
uziasferreirazup Oct 17, 2020
84d0af7
fix: adjust context data evaluation to enum
uziasferreirazup Oct 19, 2020
a4c85c9
adjust lint
uziasferreirazup Oct 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package br.com.zup.beagle.android.action

import android.view.View
import br.com.zup.beagle.android.annotation.ContextDataValue
import br.com.zup.beagle.android.context.normalizeContextValue
import br.com.zup.beagle.android.logger.BeagleLoggerProxy
import br.com.zup.beagle.android.utils.evaluateExpression
import br.com.zup.beagle.android.utils.generateViewModelInstance
Expand Down Expand Up @@ -56,7 +57,7 @@ data class SetContext(

private fun toInternalSetContext(rootView: RootView, origin: View) = SetContextInternal(
contextId = this.contextId,
value = evaluateExpression(rootView, origin, this.value)
value = evaluateExpression(rootView, origin, this.value)?.normalizeContextValue()
?: throw IllegalStateException("SetContext with id=${this.contextId} evaluated to null"),
path = this.path
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ internal class FormSubmitter(
private val beagleApi: BeagleApi = BeagleApi(),
private val deserialization: BeagleSerializer = BeagleSerializer(),
private val urlBuilder: UrlBuilder = UrlBuilderFactory().make(),
private val job:Job = Job(),
private val job: Job = Job(),
override val coroutineContext: CoroutineContext = job + Main
) : CoroutineScope {

Expand Down Expand Up @@ -86,14 +86,13 @@ internal class FormSubmitter(
}
}

private fun createUrl(form: FormRemoteAction, formsValue: Map<String, String>)
= if (form.method == FormMethodType.GET || form.method == FormMethodType.DELETE)
formsValue.filterValues {
isFormsValueValid(it)
}.toList().fold(Uri.parse(form.path).buildUpon()) { path, param ->
path.appendQueryParameter(param.first, param.second)
}.build().toString()
else form.path
private fun createUrl(form: FormRemoteAction, formsValue: Map<String, String>) = if (form.method == FormMethodType.GET || form.method == FormMethodType.DELETE)
matheusribeirozup marked this conversation as resolved.
Show resolved Hide resolved
formsValue.filterValues {
isFormsValueValid(it)
}.toList().fold(Uri.parse(form.path).buildUpon()) { path, param ->
path.appendQueryParameter(param.first, param.second)
}.build().toString()
else form.path

private fun isFormsValueValid(value: String?) = !value.isNullOrEmpty()
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,35 +56,75 @@ internal class ContextDataEvaluation(
evaluatedBindings: MutableMap<String, Any> = mutableMapOf()
): Any? {
val expressions = bind.expressions
val response = getExpressionEvaluated(contextsData, bind, contextCache, evaluatedBindings, expressions)
val type = getType(response.toString())
return deserializeExpression(bind, expressions, type, response)
}

return when {
bind.type == String::class.java -> {
val evaluatedExpressions = mutableMapOf<String, Any>()
expressions.forEach { expressionToken ->
evaluateExpressionsForContext(
contextsData,
contextCache,
expressionToken,
bind,
evaluatedExpressions,
evaluatedBindings
)
private fun deserializeExpression(
bind: Bind.Expression<*>,
expressions: List<ExpressionToken>,
type: Type?,
response: Any?): Any? {
uziasferreirazup marked this conversation as resolved.
Show resolved Hide resolved
return try {
return when {
bind.type == String::class.java -> response ?: ""
expressions.size == 1 && type == null -> response
else -> {
val newType = if (bind.type == Any::class.java) type else bind.type
moshi.adapter<Any>(newType ?: bind.type).fromJson(response.toString())
?: showLogErrorAndReturn(bind)
}

contextExpressionReplacer.replace(bind, evaluatedExpressions)
}
expressions.size == 1 -> evaluateExpression(

} catch (ex: Exception) {
showLogErrorAndReturn(bind)
null
}
}

private fun getExpressionEvaluated(
contextsData: List<ContextData>,
bind: Bind.Expression<*>,
contextCache: LruCache<String, Any>?,
evaluatedBindings: MutableMap<String, Any>,
expressions: List<ExpressionToken>): Any? {
return if (expressions.size == 1 && bind.value == "@{${bind.expressions[0].value}}") {
evaluateExpression(
contextsData,
contextCache,
bind,
expressions[0],
evaluatedBindings
)
else -> {
BeagleMessageLogs.multipleExpressionsInValueThatIsNotString()
null
}
} else evaluateMultipleExpression(expressions, contextsData, contextCache, bind, evaluatedBindings)
}

private fun evaluateMultipleExpression(
expressions: List<ExpressionToken>,
contextsData: List<ContextData>,
contextCache: LruCache<String, Any>?,
bind: Bind.Expression<*>,
evaluatedBindings: MutableMap<String, Any>): String {
val evaluatedExpressions = mutableMapOf<String, Any>()
expressions.forEach { expressionToken ->
evaluateExpressionsForContext(
contextsData,
contextCache,
expressionToken,
bind,
evaluatedExpressions,
evaluatedBindings
)
}

return contextExpressionReplacer.replace(bind, evaluatedExpressions)
}

private fun getType(json: String): Type? {
val valueNormalized = json.normalizeContextValue()
if (valueNormalized is JSONArray || valueNormalized is JSONObject) return valueNormalized::class.java
return null
}

@Suppress("LongParameterList")
Expand Down Expand Up @@ -112,20 +152,7 @@ internal class ContextDataEvaluation(
expressionToken: ExpressionToken,
evaluatedBindings: MutableMap<String, Any>
): Any? {
val value = getValueFromExpression(contextsData, expressionToken, contextCache, bind, evaluatedBindings)

return try {
if (bind.type == String::class.java) {
value?.toString() ?: showLogErrorAndReturn(bind)
} else if (value is JSONArray || value is JSONObject) {
moshi.adapter<Any>(bind.type).fromJson(value.toString()) ?: showLogErrorAndReturn(bind)
} else {
value ?: showLogErrorAndReturn(bind)
}
} catch (ex: Exception) {
BeagleMessageLogs.errorWhileTryingToNotifyContextChanges(ex)
null
}
return getValueFromExpression(contextsData, expressionToken, contextCache, bind, evaluatedBindings)
}

private fun getValueFromExpression(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package br.com.zup.beagle.android.context

import br.com.zup.beagle.android.data.serializer.BeagleMoshi
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject

/*
Expand All @@ -34,15 +35,19 @@ internal fun Any.normalizeContextValue(): Any {
this
} else {
val newValue = BeagleMoshi.moshi.adapter(Any::class.java).toJson(this) ?: ""
return newValue.normalizeContextValue()
newValue.normalizeContextValue()
}
}

internal fun String.normalizeContextValue(): Any {
return when {
this.startsWith("{") -> JSONObject(this)
this.startsWith("[") -> JSONArray(this)
else -> this
return try {
JSONObject(this)
} catch (ex: JSONException) {
try {
JSONArray(this)
} catch (ex1: JSONException) {
this
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,6 @@ internal class ContextDataManager(
GlobalContext.clearObserverGlobalContext(globalContextObserver)
}

fun clearContext(view: View) {
contexts.remove(view.id)
viewBinding.remove(view)
}

fun addContext(view: View, context: ContextData) {
if (context.id == globalContext.context.id) {
BeagleMessageLogs.globalKeywordIsReservedForGlobalContext()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class ContextExpressionReplacer {
if (isNotTheLastMatch(index, listInReverseOrderOfStringsToEvaluate)) {
val nextStringItem = listInReverseOrderOfStringsToEvaluate[index + 1]
listInReverseOrderOfStringsToEvaluate[index + 1] = nextStringItem.plus(actualStringToEvaluate)
}else{
} else {
evaluatedItemsInReverseOrder.add(actualStringToEvaluate)
}
}
Expand All @@ -114,10 +114,15 @@ class ContextExpressionReplacer {
actualStringToEvaluate: String
): String {
val valueToChangeInEvaluation = matchResult.groupValues[2]
val evaluatedValueToBeReplaced = evaluatedExpressions[valueToChangeInEvaluation].toString()
val evaluatedValueToBeReplaced = evaluatedExpressions[valueToChangeInEvaluation]
var valueReplaced = "@{$valueToChangeInEvaluation}"
val newType = "\"@{$valueToChangeInEvaluation}\""
if (evaluatedValueToBeReplaced !is String && actualStringToEvaluate.contains(newType)) {
valueReplaced = newType
}
return actualStringToEvaluate
.replace("@{$valueToChangeInEvaluation}", evaluatedValueToBeReplaced)
.replace(valueReplaced, evaluatedValueToBeReplaced.toString())
}

private fun isQuantityEven(quantity: Int) = quantity %2 == 0
private fun isQuantityEven(quantity: Int) = quantity % 2 == 0
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ import br.com.zup.beagle.android.context.ContextActionExecutor
import br.com.zup.beagle.android.context.ContextData
import br.com.zup.beagle.android.context.expressionOf
import br.com.zup.beagle.android.context.hasExpression
import br.com.zup.beagle.android.context.tokenizer.function.builtin.toJSONArray
import br.com.zup.beagle.android.logger.BeagleMessageLogs
import br.com.zup.beagle.android.utils.HandleEventDeprecatedConstants.HANDLE_EVENT_ACTIONS_POINTER
import br.com.zup.beagle.android.utils.HandleEventDeprecatedConstants.HANDLE_EVENT_DEPRECATED_MESSAGE
import br.com.zup.beagle.android.utils.HandleEventDeprecatedConstants.HANDLE_EVENT_POINTER
import br.com.zup.beagle.android.widget.RootView
import java.lang.reflect.Type

internal var contextActionExecutor = ContextActionExecutor()

Expand Down Expand Up @@ -144,6 +146,5 @@ internal fun Action.evaluateExpression(rootView: RootView, view: View, data: Any
}

private fun String.generateBindAndEvaluateForAction(rootView: RootView, view: View, caller: Action): Any? {
return expressionOf<String>(this)
.evaluateForAction(rootView, view, caller)?.tryToDeserialize()
return expressionOf<Any>(this).evaluateForAction(rootView, view, caller)
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
package br.com.zup.beagle.android.utils

internal object BeagleRegex {
val EXPRESSION_REGEX = "(\\\\*)@\\{(([^'\\}]|('([^'\\\\]|\\\\.)*'))*)\\}".toRegex()
val FULL_MATCH_EXPRESSION_SEPARATOR_REGEX = "(?<=\\})".toRegex()
val EXPRESSION_REGEX = "(\\\\*)\"?@\\{(([^'\\}]|('([^'\\\\]|\\\\.)*'))*)\\}\"?".toRegex()
val FULL_MATCH_EXPRESSION_SEPARATOR_REGEX = "(?<=\\}\"?)".toRegex()
val QUANTITY_OF_SLASHES_REGEX = "(\\\\*)@".toRegex()
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import br.com.zup.beagle.android.utils.BeagleRetry
import br.com.zup.beagle.android.utils.DeprecationMessages.DEPRECATED_STATE_LOADING
import br.com.zup.beagle.android.utils.NewIntentDeprecatedConstants
import br.com.zup.beagle.android.utils.toComponent
import br.com.zup.beagle.android.utils.tryToDeserialize
import br.com.zup.beagle.android.view.viewmodel.BeagleViewModel
import br.com.zup.beagle.android.view.viewmodel.ViewState
import br.com.zup.beagle.core.ServerDrivenComponent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@ package br.com.zup.beagle.android.view.mapper

import br.com.zup.beagle.android.action.RequestActionMethod
import br.com.zup.beagle.android.action.SendRequestInternal
import br.com.zup.beagle.android.annotation.ContextDataValue
import br.com.zup.beagle.android.context.normalizeContextValue
import br.com.zup.beagle.android.data.formatUrl
import br.com.zup.beagle.android.data.serializer.BeagleMoshi
import br.com.zup.beagle.android.networking.HttpMethod
import br.com.zup.beagle.android.networking.RequestData
import br.com.zup.beagle.android.networking.ResponseData
import br.com.zup.beagle.android.utils.tryToDeserialize
import br.com.zup.beagle.android.view.viewmodel.Response
import java.net.URI

Expand Down Expand Up @@ -62,8 +60,5 @@ internal object SendRequestActionMapper {
)
}

private fun getDataFormatted(byteData: ByteArray): Any? {
val data = String(byteData)
return data.tryToDeserialize()
}
private fun getDataFormatted(byteData: ByteArray): Any? = String(byteData).normalizeContextValue()
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class FormSubmitterTest : BaseTest() {
@MockK
private lateinit var beagleApi: BeagleApi

@MockK
@MockK(relaxed = true, relaxUnitFun = true)
private lateinit var beagleSerializer: BeagleSerializer

@MockK
Expand All @@ -77,20 +77,20 @@ class FormSubmitterTest : BaseTest() {

every { Uri.parse(any()) } returns uri
every { uri.buildUpon() } returns uriBuilder
every {uriBuilder.appendQueryParameter(any(), any())} returns uriBuilder
every {uriBuilder.build()} returns uri
every { uriBuilder.appendQueryParameter(any(), any()) } returns uriBuilder
every { uriBuilder.build() } returns uri
every { uri.toString() } returns ACTION

every { beagleSdk.config.baseUrl } returns RandomData.httpUrl()
coEvery { beagleApi.fetchData(capture(requestDataSlot)) } returns mockk()
coEvery { beagleApi.fetchData(capture(requestDataSlot)) } returns mockk(relaxed = true)
every { urlBuilder.format(any(), capture(urlSlot)) } returns ACTION

formSubmitter = FormSubmitter(beagleApi, beagleSerializer, urlBuilder)

}

@Test
fun submitForm_should_create_requestData_correctly() = runBlockingTest{
fun submitForm_should_create_requestData_correctly() = runBlockingTest {
// Given
val action = createAction(FormMethodType.POST)
val inputName = RandomData.string()
Expand Down