diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/deserializer/LambdaEventDeserializer.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/deserializer/LambdaEventDeserializer.kt new file mode 100644 index 0000000000..07650160d6 --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/deserializer/LambdaEventDeserializer.kt @@ -0,0 +1,68 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.deserializer + +import com.google.gson.JsonDeserializationContext +import com.google.gson.JsonDeserializer +import com.google.gson.JsonElement +import com.navi.ap.common.lambda.verticals.generic.event.CancelCoroutineJobEvent +import com.navi.ap.common.lambda.verticals.generic.event.CustomBanksDataFilterHandlingEvent +import com.navi.ap.common.lambda.verticals.generic.event.DelayEvent +import com.navi.ap.common.lambda.verticals.generic.event.FailureActionEvent +import com.navi.ap.common.lambda.verticals.generic.event.PreExecutionActionEvent +import com.navi.ap.common.lambda.verticals.generic.event.ReturnPastApiResponseEvent +import com.navi.ap.common.lambda.verticals.generic.event.SetClonedScreenDefinitionStateEvent +import com.navi.ap.common.lambda.verticals.generic.event.SuccessActionEvent +import com.navi.ap.common.lambda.verticals.generic.event.TriggerApiEvent +import com.navi.ap.common.lambda.verticals.generic.event.UpdateAndTriggerSuccessActionEvent +import com.navi.ap.common.lambda.verticals.generic.event.UpdateScreenDefinitionEvent +import com.navi.common.uitron.model.LambdaAppEventType +import com.navi.common.uitron.model.LambdaEventData +import java.lang.reflect.Type + +class LambdaEventDeserializer : JsonDeserializer { + override fun deserialize( + json: JsonElement?, + typeOfT: Type?, + context: JsonDeserializationContext? + ): LambdaEventData? { + json?.let { + val jsonObject = it.asJsonObject + val type = jsonObject["eventType"] ?: return null + return when (type.asString) { + LambdaAppEventType.CANCEL_COROUTINE_JOB.name -> + context?.deserialize(jsonObject, CancelCoroutineJobEvent::class.java) + LambdaAppEventType.PRE_EXECUTION_ACTION.name -> + context?.deserialize(jsonObject, PreExecutionActionEvent::class.java) + LambdaAppEventType.TRIGGER_API.name -> + context?.deserialize(jsonObject, TriggerApiEvent::class.java) + LambdaAppEventType.RETURN_PAST_API_RESPONSE.name -> + context?.deserialize(jsonObject, ReturnPastApiResponseEvent::class.java) + LambdaAppEventType.SUCCESS_ACTION.name -> + context?.deserialize(jsonObject, SuccessActionEvent::class.java) + LambdaAppEventType.FAILURE_ACTION.name -> + context?.deserialize(jsonObject, FailureActionEvent::class.java) + LambdaAppEventType.DELAY.name -> + context?.deserialize(jsonObject, DelayEvent::class.java) + LambdaAppEventType.UPDATE_AND_TRIGGER_SUCCESS_ACTION.name -> + context?.deserialize(jsonObject, UpdateAndTriggerSuccessActionEvent::class.java) + LambdaAppEventType.UPDATE_SCREEN_DEFINITION.name -> + context?.deserialize(jsonObject, UpdateScreenDefinitionEvent::class.java) + LambdaAppEventType.SET_CLONED_SCREEN_DEFINITION_STATE.name -> + context?.deserialize( + jsonObject, + SetClonedScreenDefinitionStateEvent::class.java + ) + LambdaAppEventType.CUSTOM_BANKS_DATA_FILTER_HANDLING.name -> + context?.deserialize(jsonObject, CustomBanksDataFilterHandlingEvent::class.java) + else -> null + } + } + return null + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/handler/LambdaHandler.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/handler/LambdaHandler.kt index 3a6818ecbe..99d969eea9 100644 --- a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/handler/LambdaHandler.kt +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/handler/LambdaHandler.kt @@ -9,9 +9,14 @@ package com.navi.ap.common.lambda.handler import com.navi.ap.common.lambda.definition.Lambda import com.navi.ap.common.lambda.definition.LambdaBridge +import com.navi.ap.common.lambda.verticals.generic.GenericLambdaImpl import com.navi.ap.common.models.ApScreenDefinitionStructure import com.navi.ap.common.models.lambdamodels.LambdaData +import com.navi.ap.utils.constants.GENERIC_LAMBDA_INIT +import com.navi.ap.utils.constants.METHOD_NAME +import com.navi.ap.utils.logApEvent import com.navi.common.uitron.model.action.LambdaApiAction +import com.navi.common.utils.Constants.TYPE import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update @@ -25,9 +30,22 @@ abstract class LambdaHandler( clonedScreenDefinitionState.update { screenDefinitionState } } + private val lambdaImpl by lazy { GenericLambdaImpl(lambdaHandler = this) } + fun getClonedScreenDefinitionState() = clonedScreenDefinitionState.value override fun execute(lambdaApiAction: LambdaApiAction, lambadaData: LambdaData) { // TODO : Put Common lambda here } + + fun executeGenericLambda(lambdaApiAction: LambdaApiAction, lambadaData: LambdaData) { + logApEvent( + Pair(TYPE, lambdaApiAction.lambdaType.orEmpty()), + Pair(METHOD_NAME, GENERIC_LAMBDA_INIT) + ) + lambdaImpl.executeGenericLambda( + lambdaApiAction = lambdaApiAction, + resolvedValues = lambadaData.resolvedValue.toMutableMap() + ) + } } diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/coins/CoinsLambdaHandler.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/coins/CoinsLambdaHandler.kt index 5eb19154f3..a10777eed4 100644 --- a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/coins/CoinsLambdaHandler.kt +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/coins/CoinsLambdaHandler.kt @@ -9,6 +9,7 @@ package com.navi.ap.common.lambda.verticals.coins import com.navi.ap.common.lambda.definition.LambdaBridge import com.navi.ap.common.lambda.handler.LambdaHandler +import com.navi.ap.common.lambda.verticals.generic.isLambdaDefinitionPresent import com.navi.ap.common.models.lambdamodels.LambdaData import com.navi.ap.utils.constants.LambdaType import com.navi.common.uitron.model.action.LambdaApiAction @@ -21,7 +22,10 @@ internal class CoinsLambdaHandler( private val lambdaImpl by lazy { CoinLambdaImpl(lambdaHandler = this@CoinsLambdaHandler) } override fun execute(lambdaApiAction: LambdaApiAction, lambadaData: LambdaData) { - + if (isLambdaDefinitionPresent(lambdaApiAction)) { + executeGenericLambda(lambdaApiAction, lambadaData) + return + } when (lambdaApiAction.lambdaType) { LambdaType.VALIDATE_COINS_UPI_ID.name -> { lambdaImpl.validateCoinsUPIId( diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/GenericLambdaHelper.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/GenericLambdaHelper.kt new file mode 100644 index 0000000000..9ce0339b7d --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/GenericLambdaHelper.kt @@ -0,0 +1,152 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic + +import com.navi.analytics.utils.NaviTrackEvent +import com.navi.ap.common.lambda.getErrorBottomSheetStructureAndSetLambdaState +import com.navi.ap.common.lambda.handler.LambdaHandler +import com.navi.ap.common.lambda.verticals.generic.event.LambdaEventFactory +import com.navi.ap.common.models.LambdaResponseType +import com.navi.ap.common.models.LambdaState +import com.navi.ap.common.models.lambdamodels.LambdaEventDetails +import com.navi.ap.network.retrofit.ApRepoResult +import com.navi.ap.utils.constants.EVENT +import com.navi.ap.utils.constants.GENERIC_LAMBDA_HANDLE_LAMBDA_STATE +import com.navi.ap.utils.constants.GENERIC_LAMBDA_TRIGGER_OUT_OF_SCOPE +import com.navi.ap.utils.constants.GENERIC_LAMBDA_TRIGGER_SCOPE +import com.navi.ap.utils.constants.METHOD_NAME +import com.navi.ap.utils.getValueAtJsonPath +import com.navi.ap.utils.logApEvent +import com.navi.common.uitron.model.LambdaResponseInjectionField +import com.navi.common.uitron.model.LambdaStateType +import com.navi.common.uitron.model.action.ApiType +import com.navi.common.uitron.model.action.LambdaApiAction +import com.navi.common.utils.Constants +import com.navi.common.utils.log +import org.mvel2.MVEL + +class GenericLambdaHelper( + val lambdaHandler: LambdaHandler, + private val lambdaEventFactory: LambdaEventFactory = LambdaEventFactory() +) { + + fun handleOutOfScopeEvents(details: LambdaEventDetails) { + logApEvent( + Pair(Constants.TYPE, details.lambdaApiAction.lambdaType.orEmpty()), + Pair(METHOD_NAME, GENERIC_LAMBDA_TRIGGER_OUT_OF_SCOPE), + Pair(EVENT, details.lambdaEventData?.eventType.orEmpty()) + ) + lambdaEventFactory + .createOutOfScopeEventExecutor(type = details.lambdaEventData?.eventType) + ?.handleOutOfScopeEvent(details) + } + + suspend fun handleScopeEvents(details: LambdaEventDetails) { + logApEvent( + Pair(Constants.TYPE, details.lambdaApiAction.lambdaType.orEmpty()), + Pair(METHOD_NAME, GENERIC_LAMBDA_TRIGGER_SCOPE), + Pair(EVENT, details.lambdaEventData?.eventType.orEmpty()) + ) + details.lambdaEventData?.let { + lambdaEventFactory + .createScopeEventExecutor( + details = details, + handleOutOfScopeEvents = ::handleOutOfScopeEvents + ) + ?.handleScopeEvent(details) + } + } + + fun handleLambdaState( + lambdaApiAction: LambdaApiAction, + stateType: String?, + lambdaResponse: ApRepoResult = ApRepoResult() + ) { + stateType?.let { + logApEvent( + Pair(Constants.TYPE, lambdaApiAction.lambdaType.orEmpty()), + Pair(METHOD_NAME, GENERIC_LAMBDA_HANDLE_LAMBDA_STATE), + Pair(EVENT, it) + ) + when (it) { + LambdaStateType.LOADING.name -> { + lambdaHandler.bridge.setLambdaState(LambdaState.Loading) + } + LambdaStateType.SUCCESS.name -> { + lambdaHandler.bridge.setLambdaState(LambdaState.Success(LambdaResponseType())) + } + LambdaStateType.ERROR.name -> { + lambdaHandler.bridge.setLambdaState( + LambdaState.Error( + lambdaResponse.statusCode, + lambdaResponse.errorBottomSheetStructure, + lambdaResponse.genericErrorBottomSheetFields + ) + ) + } + LambdaStateType.CUSTOM_ERROR.name -> { + getErrorBottomSheetStructureAndSetLambdaState( + lambdaApiAction.definition?.implementation?.apiTag + ?: ApiType.LambdaApiAction.name, + lambdaResponse.statusCode + ) + } + LambdaStateType.NOTHING.name -> { + lambdaHandler.bridge.setLambdaState(LambdaState.Nothing) + } + else -> {} + } + } + } + + fun updateHandle( + handleConfig: List?, + resolvedValues: MutableMap, + lambdaResponse: ApRepoResult = ApRepoResult(), + ) { + handleConfig?.forEach { + val key = getValueAtJsonPath(resolvedValues, it?.key.orEmpty()).toString() + val value = + if (it?.jsonPath.isNullOrEmpty()) { + lambdaResponse.data + } else { + getValueAtJsonPath(lambdaResponse.data ?: Any(), it?.jsonPath.orEmpty()) + ?: lambdaResponse.data + } + lambdaHandler.bridge.getSaveStateHandle()[key] = value + } + } + + fun evaluateMvelExpression( + expression: String?, + updatedResolvedValues: MutableMap, + lambdaResponse: ApRepoResult = ApRepoResult(), + pastApiResponse: HashMap?> + ): Any? { + if (expression.isNullOrEmpty()) return null + val varsMap = + mapOf( + Pair("data", lambdaResponse.data), + Pair("errors", lambdaResponse.errors), + Pair("errorBottomSheetStructure", lambdaResponse.errorBottomSheetStructure), + Pair("resolvedValues", updatedResolvedValues), + Pair("pastApiResponse", pastApiResponse), + Pair("lambdaHandler", lambdaHandler), + ) + try { + return MVEL.eval(expression, varsMap) + } catch (e: Exception) { + e.log() + NaviTrackEvent.trackEvent( + eventName = "dev_evaluate_generic_lambda_mvel_expression_result", + eventValues = mapOf(Pair("mvelExpression", expression)) + ) + } + return null + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/GenericLambdaImpl.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/GenericLambdaImpl.kt new file mode 100644 index 0000000000..c80fea19d7 --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/GenericLambdaImpl.kt @@ -0,0 +1,210 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic + +import com.navi.ap.common.lambda.handler.LambdaHandler +import com.navi.ap.common.models.lambdamodels.LambdaEventDetails +import com.navi.ap.network.retrofit.ApRepoResult +import com.navi.ap.utils.constants.GENERIC_LAMBDA_PAST_API_RESPONSE +import com.navi.ap.utils.constants.GENERIC_LAMBDA_TRIGGER_POST_LAUNCH +import com.navi.ap.utils.constants.GENERIC_LAMBDA_TRIGGER_PRE_LAUNCH +import com.navi.ap.utils.constants.METHOD_NAME +import com.navi.ap.utils.constants.TRUE +import com.navi.ap.utils.logApEvent +import com.navi.common.CommonLibManager +import com.navi.common.uitron.model.action.LambdaApiAction +import com.navi.common.utils.Constants +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch + +internal class GenericLambdaImpl(private val lambdaHandler: LambdaHandler) { + + private val repository: GenericLambdaRepository = + GenericLambdaProvider().getRepository(CommonLibManager.application.applicationContext) + + private val lambdaHelper by lazy { GenericLambdaHelper(lambdaHandler) } + + private val coroutineJobs by lazy { hashMapOf() } + + private val pastApiResponse by lazy { hashMapOf?>() } + + fun executeGenericLambda( + lambdaApiAction: LambdaApiAction, + resolvedValues: MutableMap, + ) { + if (areRequiredInputsPresent(lambdaApiAction, resolvedValues).not()) { + return + } + triggerPreLaunchEvents(lambdaApiAction, resolvedValues).let { isLambdaResolved -> + if (isLambdaResolved) return + } + coroutineJobs[lambdaApiAction.lambdaType.orEmpty()] = + lambdaHandler.bridge.getViewModelScope().launch(Dispatchers.IO) { + val response = triggerPostLaunchEvents(lambdaApiAction, resolvedValues) + pastApiResponse[lambdaApiAction.lambdaType.orEmpty()] = response + handleLambdaApiResponse(lambdaApiAction, resolvedValues, response) + } + } + + private fun triggerPreLaunchEvents( + lambdaApiAction: LambdaApiAction, + resolvedValues: MutableMap + ): Boolean { + logApEvent( + Pair(Constants.TYPE, lambdaApiAction.lambdaType.orEmpty()), + Pair(METHOD_NAME, GENERIC_LAMBDA_TRIGGER_PRE_LAUNCH) + ) + lambdaApiAction.definition?.implementation?.preLaunchEvents?.forEach { event -> + val condition = getImplementationSuccessCondition(lambdaApiAction, event) + val status = evaluateExpression(condition, resolvedValues) + handlePreLaunchLambdaStateAndAppEvents(event, status, lambdaApiAction, resolvedValues) + + val handleConfig = getResponseState(lambdaApiAction, event, status)?.handleConfig + return if (handleConfig.isNullOrEmpty().not()) { + lambdaHelper.updateHandle(handleConfig, resolvedValues) + true + } else { + false + } + } + return false + } + + private suspend fun triggerPostLaunchEvents( + lambdaApiAction: LambdaApiAction, + resolvedValues: MutableMap + ): ApRepoResult { + logApEvent( + Pair(Constants.TYPE, lambdaApiAction.lambdaType.orEmpty()), + Pair(METHOD_NAME, GENERIC_LAMBDA_TRIGGER_POST_LAUNCH) + ) + lambdaApiAction.definition?.implementation?.postLaunchEvents?.forEach { event -> + val condition = getImplementationSuccessCondition(lambdaApiAction, event) + val status = evaluateExpression(condition, resolvedValues) + + handlePostLaunchLambdaStateAndAppEvents(event, status, lambdaApiAction, resolvedValues) + + if (isTriggerApiEvent(lambdaApiAction, event, status) && status == TRUE) { + return repository.triggerGenericLambda(lambdaApiAction, resolvedValues) + } else if (isPastApiResponseEvent(lambdaApiAction, event, status) && status == TRUE) { + logApEvent( + Pair(Constants.TYPE, lambdaApiAction.lambdaType.orEmpty()), + Pair(METHOD_NAME, GENERIC_LAMBDA_PAST_API_RESPONSE) + ) + return pastApiResponse[lambdaApiAction.lambdaType.orEmpty()] ?: ApRepoResult() + } + + val handleConfig = getResponseState(lambdaApiAction, event, status)?.handleConfig + if (handleConfig.isNullOrEmpty().not()) { + lambdaHelper.updateHandle(handleConfig, resolvedValues) + return ApRepoResult() + } + } + return ApRepoResult() + } + + private fun handlePreLaunchLambdaStateAndAppEvents( + event: String, + status: String, + lambdaApiAction: LambdaApiAction, + resolvedValues: MutableMap + ) { + val lambdaState = getResponseState(lambdaApiAction, event, status)?.lambdaState + lambdaHelper.handleLambdaState(lambdaApiAction, lambdaState?.stateType) + + getResponseState(lambdaApiAction, event, status)?.appEvents?.forEach { eventData -> + lambdaHelper.handleOutOfScopeEvents( + LambdaEventDetails( + lambdaEventData = eventData, + lambdaApiAction = lambdaApiAction, + resolvedValues = resolvedValues, + coroutineJobs = coroutineJobs, + lambdaHandler = lambdaHandler + ) + ) + } + } + + private suspend fun handlePostLaunchLambdaStateAndAppEvents( + event: String, + status: String, + lambdaApiAction: LambdaApiAction, + resolvedValues: MutableMap + ) { + val lambdaState = getResponseState(lambdaApiAction, event, status)?.lambdaState + lambdaHelper.handleLambdaState(lambdaApiAction, lambdaState?.stateType) + + getResponseState(lambdaApiAction, event, status)?.appEvents?.forEach { stateData -> + lambdaHelper.handleScopeEvents( + LambdaEventDetails( + lambdaEventData = stateData, + lambdaApiAction = lambdaApiAction, + resolvedValues = resolvedValues, + coroutineJobs = coroutineJobs, + lambdaHandler = lambdaHandler + ) + ) + } + } + + private suspend fun handleLambdaApiResponse( + lambdaApiAction: LambdaApiAction?, + resolvedValues: MutableMap, + lambdaResponse: ApRepoResult + ) { + lambdaApiAction?.definition?.implementation?.conditions?.forEach { (event, state) -> + if (isEventExecuted(lambdaApiAction, event)) { + return@forEach + } + + val status = evaluateExpression(state?.success, resolvedValues, lambdaResponse) + + val handleConfig = getResponseState(lambdaApiAction, event, status)?.handleConfig + if (handleConfig.isNullOrEmpty().not()) { + lambdaHelper.updateHandle(handleConfig, resolvedValues, lambdaResponse) + } + + val appEvents = getResponseState(lambdaApiAction, event, status)?.appEvents + appEvents?.forEach { eventData -> + lambdaHelper.handleScopeEvents( + LambdaEventDetails( + lambdaEventData = eventData, + lambdaApiAction = lambdaApiAction, + resolvedValues = resolvedValues, + coroutineJobs = coroutineJobs, + lambdaResponse = lambdaResponse, + lambdaHandler = lambdaHandler + ) + ) + } + + val lambdaState = getResponseState(lambdaApiAction, event, status)?.lambdaState + lambdaHelper.handleLambdaState(lambdaApiAction, lambdaState?.stateType, lambdaResponse) + + if (status == TRUE) { + return + } + } + } + + private fun evaluateExpression( + expression: String?, + updatedResolvedValues: MutableMap, + lambdaResponse: ApRepoResult = ApRepoResult() + ): String { + return lambdaHelper + .evaluateMvelExpression( + expression, + updatedResolvedValues, + lambdaResponse, + pastApiResponse + ) + .toString() + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/GenericLambdaProvider.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/GenericLambdaProvider.kt new file mode 100644 index 0000000000..a00646ba88 --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/GenericLambdaProvider.kt @@ -0,0 +1,24 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic + +import android.content.Context +import com.navi.ap.di.EntryPoints +import dagger.hilt.android.EntryPointAccessors + +internal class GenericLambdaProvider { + + fun getRepository(context: Context): GenericLambdaRepository { + val hiltEntryPoint = + EntryPointAccessors.fromApplication( + context, + EntryPoints.GenericLambdaRepositoryEntryPoint::class.java + ) + return hiltEntryPoint.getGenericLambdaRepository() + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/GenericLambdaRepository.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/GenericLambdaRepository.kt new file mode 100644 index 0000000000..04e4afe212 --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/GenericLambdaRepository.kt @@ -0,0 +1,89 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic + +import com.navi.ap.data.repository.ApplicationPlatformRepositoryImp +import com.navi.ap.network.retrofit.ApRepoResult +import com.navi.ap.network.retrofit.service.APRetrofitService +import com.navi.ap.utils.constants.GENERIC_LAMBDA_TRIGGER_API +import com.navi.ap.utils.constants.METHOD_NAME +import com.navi.ap.utils.constants.RESULT +import com.navi.ap.utils.constants.STATUS_CODE +import com.navi.ap.utils.getValueAtJsonPath +import com.navi.ap.utils.injectValuesInAStringWithPlaceHolders +import com.navi.ap.utils.injector.PathInjector +import com.navi.ap.utils.logApEvent +import com.navi.common.uitron.model.ApiRequestType +import com.navi.common.uitron.model.action.ApiType +import com.navi.common.uitron.model.action.LambdaApiAction +import com.navi.common.utils.Constants +import javax.inject.Inject + +class GenericLambdaRepository @Inject constructor(private val retrofitService: APRetrofitService) : + ApplicationPlatformRepositoryImp(retrofitService) { + + suspend fun triggerGenericLambda( + lambdaApiAction: LambdaApiAction, + resolvedValues: MutableMap, + ): ApRepoResult { + logApEvent( + Pair(Constants.TYPE, lambdaApiAction.lambdaType.orEmpty()), + Pair(METHOD_NAME, GENERIC_LAMBDA_TRIGGER_API) + ) + val request = lambdaApiAction.definition?.implementation?.request ?: return ApRepoResult() + + val headerMap: MutableMap = mutableMapOf() + request.headers + ?.filter { it.value != null } + ?.forEach { + headerMap[it.key] = + getValueAtJsonPath(resolvedValues, it.value.orEmpty()).toString() + } + + val subUrl = injectValuesInAStringWithPlaceHolders(request.subUrl.orEmpty(), resolvedValues) + + val requestBody = + PathInjector().injectData(request.body ?: Any(), resolvedValues) + + val response = + when (request.method) { + ApiRequestType.GET.name -> { + retrofitService.getRequest(subUrl, headerMap) + } + ApiRequestType.POST.name -> { + retrofitService.postRequest(subUrl, headerMap, requestBody) + } + ApiRequestType.PATCH.name -> { + retrofitService.patchRequest(subUrl, headerMap, requestBody) + } + ApiRequestType.DELETE.name -> { + retrofitService.deleteRequest(subUrl, headerMap) + } + ApiRequestType.PUT.name -> { + retrofitService.putRequest(subUrl, headerMap, requestBody) + } + else -> { + return ApRepoResult() + } + } + + logApEvent( + Pair( + RESULT, + "${response.body()?.errors} | ${response.body()?.genericErrorBottomSheetFields}" + ), + Pair(METHOD_NAME, ::triggerGenericLambda.name), + Pair(STATUS_CODE, response.code().toString()) + ) + return apiResponseCallback( + response = response, + apiTag = + lambdaApiAction.definition?.implementation?.apiTag ?: ApiType.LambdaApiAction.name + ) + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/GenericLambdaUtils.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/GenericLambdaUtils.kt new file mode 100644 index 0000000000..699747a48e --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/GenericLambdaUtils.kt @@ -0,0 +1,72 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic + +import com.navi.ap.utils.constants.TRUE +import com.navi.base.utils.orFalse +import com.navi.common.uitron.model.LambdaAppEventType +import com.navi.common.uitron.model.LambdaResponse +import com.navi.common.uitron.model.LambdaResponseConfig +import com.navi.common.uitron.model.action.LambdaApiAction + +fun isLambdaDefinitionPresent(lambdaApiAction: LambdaApiAction): Boolean { + return lambdaApiAction.definition != null +} + +fun areRequiredInputsPresent( + lambdaApiAction: LambdaApiAction, + resolvedValues: MutableMap +): Boolean { + lambdaApiAction.definition?.contract?.input?.forEach { + if (it.value?.isRequired.orFalse() && resolvedValues[it.key] == null) { + return false + } + } + return true +} + +fun LambdaResponse?.getSuccessOrFailureState(status: String): LambdaResponseConfig? { + return if (status == TRUE) this?.success else this?.failure +} + +fun isEventExecuted(lambdaApiAction: LambdaApiAction?, event: String): Boolean { + return lambdaApiAction?.definition?.implementation?.preLaunchEvents?.contains(event) == true || + lambdaApiAction?.definition?.implementation?.postLaunchEvents?.contains(event) == true +} + +fun isTriggerApiEvent(lambdaApiAction: LambdaApiAction, event: String, status: String): Boolean { + val appEvents = + getResponseState(lambdaApiAction, event, status)?.appEvents?.map { it?.eventType } + return appEvents?.contains(LambdaAppEventType.TRIGGER_API.name).orFalse() +} + +fun isPastApiResponseEvent( + lambdaApiAction: LambdaApiAction, + event: String, + status: String +): Boolean { + val appEvents = + getResponseState(lambdaApiAction, event, status)?.appEvents?.map { it?.eventType } + return appEvents?.contains(LambdaAppEventType.RETURN_PAST_API_RESPONSE.name).orFalse() +} + +fun getImplementationSuccessCondition(lambdaApiAction: LambdaApiAction, event: String): String? { + return lambdaApiAction.definition?.implementation?.conditions?.get(event)?.success +} + +fun getResponseState( + lambdaApiAction: LambdaApiAction, + event: String, + status: String +): LambdaResponseConfig? { + return lambdaApiAction.definition + ?.implementation + ?.response + ?.get(event) + ?.getSuccessOrFailureState(status) +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/CancelCoroutineJobEvent.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/CancelCoroutineJobEvent.kt new file mode 100644 index 0000000000..b50e52f6f9 --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/CancelCoroutineJobEvent.kt @@ -0,0 +1,18 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic.event + +import com.navi.ap.common.models.lambdamodels.LambdaEventDetails +import com.navi.common.uitron.model.LambdaEventData + +class CancelCoroutineJobEvent : LambdaEventData(), ILambdaEventExecutor { + + override fun handleOutOfScopeEvent(details: LambdaEventDetails) { + details.coroutineJobs[details.lambdaApiAction.lambdaType.orEmpty()]?.cancel() + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/CustomBanksDataFilterHandlingEvent.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/CustomBanksDataFilterHandlingEvent.kt new file mode 100644 index 0000000000..57e27b5c0e --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/CustomBanksDataFilterHandlingEvent.kt @@ -0,0 +1,39 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic.event + +import com.navi.ap.common.models.lambdamodels.LambdaEventDetails +import com.navi.ap.common.models.lambdamodels.response.BankDataResponse +import com.navi.ap.utils.constants.ALL_BANKS_LIST +import com.navi.ap.utils.constants.BANK_SEARCH_QUERY +import com.navi.ap.utils.constants.PREFERRED_BANKS_LIST +import com.navi.ap.utils.jsonToType +import com.navi.common.uitron.model.LambdaEventData +import com.navi.common.utils.toJsonObject + +class CustomBanksDataFilterHandlingEvent : LambdaEventData(), ILambdaEventExecutor { + override suspend fun handleScopeEvent(details: LambdaEventDetails) { + val preferredBanksKey = details.resolvedValues[PREFERRED_BANKS_LIST]?.toString().orEmpty() + val allBanksKey = details.resolvedValues[ALL_BANKS_LIST]?.toString().orEmpty() + val query = details.resolvedValues[BANK_SEARCH_QUERY]?.toString().orEmpty().trim() + + val banksResponse = + details.lambdaResponse.data.toJsonObject()?.jsonToType() + + details.lambdaHandler.bridge.getSaveStateHandle()[preferredBanksKey] = + if (query.isEmpty()) banksResponse?.preferredBanks else emptyList() + val filteredBanks = + banksResponse?.allSupportedBanks?.filter { it.name?.startsWith(query, true) ?: false } + details.lambdaHandler.bridge.getSaveStateHandle()[allBanksKey] = filteredBanks + if (filteredBanks?.isNotEmpty() == true) { + details.lambdaHandler.bridge.executeActions(details.lambdaApiAction.onSuccess) + } else { + details.lambdaHandler.bridge.executeActions(details.lambdaApiAction.onFailure) + } + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/DelayEvent.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/DelayEvent.kt new file mode 100644 index 0000000000..23ae73dafc --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/DelayEvent.kt @@ -0,0 +1,26 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic.event + +import com.google.gson.annotations.SerializedName +import com.navi.ap.common.models.lambdamodels.LambdaEventDetails +import com.navi.common.uitron.model.LambdaEventData +import kotlinx.coroutines.delay + +class DelayEvent(@SerializedName("delay") val delay: Long? = null) : + LambdaEventData(), ILambdaEventExecutor { + + override suspend fun handleScopeEvent(details: LambdaEventDetails) { + val event = details.lambdaEventData as DelayEvent + delay(event.delay ?: DEFAULT_DELAY) + } + + companion object { + const val DEFAULT_DELAY = 200L + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/FailureActionEvent.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/FailureActionEvent.kt new file mode 100644 index 0000000000..e268ec0caf --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/FailureActionEvent.kt @@ -0,0 +1,18 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic.event + +import com.navi.ap.common.models.lambdamodels.LambdaEventDetails +import com.navi.common.uitron.model.LambdaEventData + +class FailureActionEvent : LambdaEventData(), ILambdaEventExecutor { + + override fun handleOutOfScopeEvent(details: LambdaEventDetails) { + details.lambdaHandler.bridge.executeActions(details.lambdaApiAction.onFailure) + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/ILambdaEventExecutor.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/ILambdaEventExecutor.kt new file mode 100644 index 0000000000..24da9d23d0 --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/ILambdaEventExecutor.kt @@ -0,0 +1,17 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic.event + +import com.navi.ap.common.models.lambdamodels.LambdaEventDetails + +interface ILambdaEventExecutor { + + fun handleOutOfScopeEvent(details: LambdaEventDetails) {} + + suspend fun handleScopeEvent(details: LambdaEventDetails) {} +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/LambdaEventFactory.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/LambdaEventFactory.kt new file mode 100644 index 0000000000..c1b17311d2 --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/LambdaEventFactory.kt @@ -0,0 +1,45 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic.event + +import com.navi.ap.common.models.lambdamodels.LambdaEventDetails +import com.navi.common.uitron.model.LambdaAppEventType + +class LambdaEventFactory { + + fun createOutOfScopeEventExecutor(type: String?): ILambdaEventExecutor? { + return when (type) { + LambdaAppEventType.CANCEL_COROUTINE_JOB.name -> CancelCoroutineJobEvent() + LambdaAppEventType.PRE_EXECUTION_ACTION.name -> PreExecutionActionEvent() + LambdaAppEventType.TRIGGER_API.name -> TriggerApiEvent() + LambdaAppEventType.SUCCESS_ACTION.name -> SuccessActionEvent() + LambdaAppEventType.FAILURE_ACTION.name -> FailureActionEvent() + else -> null + } + } + + fun createScopeEventExecutor( + details: LambdaEventDetails, + handleOutOfScopeEvents: (LambdaEventDetails) -> Unit + ): ILambdaEventExecutor? { + return when (details.lambdaEventData?.eventType) { + LambdaAppEventType.DELAY.name -> DelayEvent() + LambdaAppEventType.UPDATE_AND_TRIGGER_SUCCESS_ACTION.name -> + UpdateAndTriggerSuccessActionEvent() + LambdaAppEventType.UPDATE_SCREEN_DEFINITION.name -> UpdateScreenDefinitionEvent() + LambdaAppEventType.SET_CLONED_SCREEN_DEFINITION_STATE.name -> + SetClonedScreenDefinitionStateEvent() + LambdaAppEventType.CUSTOM_BANKS_DATA_FILTER_HANDLING.name -> + CustomBanksDataFilterHandlingEvent() + else -> { + handleOutOfScopeEvents.invoke(details) + return null + } + } + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/PreExecutionActionEvent.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/PreExecutionActionEvent.kt new file mode 100644 index 0000000000..48950f9ec4 --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/PreExecutionActionEvent.kt @@ -0,0 +1,18 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic.event + +import com.navi.ap.common.models.lambdamodels.LambdaEventDetails +import com.navi.common.uitron.model.LambdaEventData + +class PreExecutionActionEvent : LambdaEventData(), ILambdaEventExecutor { + + override fun handleOutOfScopeEvent(details: LambdaEventDetails) { + details.lambdaHandler.bridge.executeActions(details.lambdaApiAction.preExecutionAction) + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/ReturnPastApiResponseEvent.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/ReturnPastApiResponseEvent.kt new file mode 100644 index 0000000000..6e4783a43e --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/ReturnPastApiResponseEvent.kt @@ -0,0 +1,12 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic.event + +import com.navi.common.uitron.model.LambdaEventData + +class ReturnPastApiResponseEvent : LambdaEventData(), ILambdaEventExecutor diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/SetClonedScreenDefinitionStateEvent.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/SetClonedScreenDefinitionStateEvent.kt new file mode 100644 index 0000000000..5413581ba0 --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/SetClonedScreenDefinitionStateEvent.kt @@ -0,0 +1,21 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic.event + +import com.navi.ap.common.models.lambdamodels.LambdaEventDetails +import com.navi.common.uitron.model.LambdaEventData + +class SetClonedScreenDefinitionStateEvent : LambdaEventData(), ILambdaEventExecutor { + override suspend fun handleScopeEvent(details: LambdaEventDetails) { + if (details.lambdaHandler.getClonedScreenDefinitionState() == null) { + details.lambdaHandler.setClonedScreenDefinitionState( + details.lambdaHandler.bridge.getScreenStructurePreRenderState() + ) + } + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/SuccessActionEvent.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/SuccessActionEvent.kt new file mode 100644 index 0000000000..2f14825148 --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/SuccessActionEvent.kt @@ -0,0 +1,18 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic.event + +import com.navi.ap.common.models.lambdamodels.LambdaEventDetails +import com.navi.common.uitron.model.LambdaEventData + +class SuccessActionEvent : LambdaEventData(), ILambdaEventExecutor { + + override fun handleOutOfScopeEvent(details: LambdaEventDetails) { + details.lambdaHandler.bridge.executeActions(details.lambdaApiAction.onSuccess) + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/TriggerApiEvent.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/TriggerApiEvent.kt new file mode 100644 index 0000000000..a0436458e5 --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/TriggerApiEvent.kt @@ -0,0 +1,12 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic.event + +import com.navi.common.uitron.model.LambdaEventData + +class TriggerApiEvent : LambdaEventData(), ILambdaEventExecutor {} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/UpdateAndTriggerSuccessActionEvent.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/UpdateAndTriggerSuccessActionEvent.kt new file mode 100644 index 0000000000..5e09ae8471 --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/UpdateAndTriggerSuccessActionEvent.kt @@ -0,0 +1,25 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic.event + +import com.navi.ap.common.models.lambdamodels.LambdaEventDetails +import com.navi.ap.utils.injector.PathInjector +import com.navi.common.uitron.model.LambdaEventData +import com.navi.common.uitron.model.action.LambdaApiAction + +class UpdateAndTriggerSuccessActionEvent : LambdaEventData(), ILambdaEventExecutor { + + override suspend fun handleScopeEvent(details: LambdaEventDetails) { + val updatedLambdaApiAction = + if (details.lambdaResponse.data != null) { + PathInjector() + .injectData(details.lambdaApiAction, details.lambdaResponse.data) + } else details.lambdaApiAction + details.lambdaHandler.bridge.executeActions(updatedLambdaApiAction.onSuccess) + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/UpdateScreenDefinitionEvent.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/UpdateScreenDefinitionEvent.kt new file mode 100644 index 0000000000..cbd4bf40ec --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/generic/event/UpdateScreenDefinitionEvent.kt @@ -0,0 +1,59 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.lambda.verticals.generic.event + +import com.google.gson.annotations.SerializedName +import com.navi.ap.common.models.ApScreenDefinitionState +import com.navi.ap.common.models.ApScreenDefinitionStructure +import com.navi.ap.common.models.lambdamodels.LambdaEventDetails +import com.navi.ap.utils.injector.BasePathInjector +import com.navi.ap.utils.injector.PathInjector +import com.navi.common.uitron.model.LambdaEventData + +class UpdateScreenDefinitionEvent( + @SerializedName("injectorType") val injectorType: String? = null +) : LambdaEventData(), ILambdaEventExecutor { + + override suspend fun handleScopeEvent(details: LambdaEventDetails) { + val event = details.lambdaEventData as UpdateScreenDefinitionEvent + val updatedResponse = getInjectedResponse(event.injectorType, details) + updatedResponse?.let { + details.lambdaHandler.bridge.setMetaData( + updatedResponse.screenData?.metaData ?: mapOf() + ) + details.lambdaHandler.bridge.setScreenDefinitionState( + ApScreenDefinitionState.Success(updatedResponse) + ) + } + details.lambdaHandler.bridge.setSystemBackAction( + updatedResponse?.screenData?.screenStructure?.systemBackCta + ) + } +} + +suspend fun getInjectedResponse( + injectorType: String?, + details: LambdaEventDetails +): ApScreenDefinitionStructure? { + return when (injectorType) { + PathInjector.TAG -> { + PathInjector() + .injectData( + details.lambdaHandler.getClonedScreenDefinitionState(), + details.lambdaResponse.data + ) + } + else -> { + BasePathInjector() + .injectData( + details.lambdaHandler.getClonedScreenDefinitionState(), + details.lambdaResponse.data + ) + } + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/personalloan/PLLambdaHandler.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/personalloan/PLLambdaHandler.kt index 987939cc14..fcf49988c1 100644 --- a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/personalloan/PLLambdaHandler.kt +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/personalloan/PLLambdaHandler.kt @@ -9,6 +9,7 @@ package com.navi.ap.common.lambda.verticals.personalloan import com.navi.ap.common.lambda.definition.LambdaBridge import com.navi.ap.common.lambda.handler.LambdaHandler +import com.navi.ap.common.lambda.verticals.generic.isLambdaDefinitionPresent import com.navi.ap.common.models.lambdamodels.LambdaData import com.navi.ap.utils.constants.FILE_TYPE import com.navi.ap.utils.constants.HYPERVERGE_PAN_FLOW_ID @@ -33,6 +34,10 @@ open class PLLambdaHandler( private val lambdaImpl by lazy { PLLambdaImpl(lambdaHandler = this@PLLambdaHandler) } override fun execute(lambdaApiAction: LambdaApiAction, lambadaData: LambdaData) { + if (isLambdaDefinitionPresent(lambdaApiAction)) { + executeGenericLambda(lambdaApiAction, lambadaData) + return + } when (lambdaApiAction.lambdaType) { LambdaType.TELCO_RESEND_OTP.name -> { lambdaImpl.resendTelcoOtp(lambdaApiAction = lambdaApiAction) diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/vkyc/VKYCLambdaHandler.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/vkyc/VKYCLambdaHandler.kt index e5f56a9fa9..17dbacf72f 100644 --- a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/vkyc/VKYCLambdaHandler.kt +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/lambda/verticals/vkyc/VKYCLambdaHandler.kt @@ -9,6 +9,7 @@ package com.navi.ap.common.lambda.verticals.vkyc import com.navi.ap.common.lambda.definition.LambdaBridge import com.navi.ap.common.lambda.definition.VkycLambdaBridge +import com.navi.ap.common.lambda.verticals.generic.isLambdaDefinitionPresent import com.navi.ap.common.lambda.verticals.personalloan.PLLambdaHandler import com.navi.ap.common.models.lambdamodels.LambdaData import com.navi.ap.utils.constants.LambdaType @@ -21,6 +22,10 @@ internal class VKYCLambdaHandler( private val lambdaImpl by lazy { VKYCLambdaImpl(lambdaHandler = this@VKYCLambdaHandler) } override fun execute(lambdaApiAction: LambdaApiAction, lambadaData: LambdaData) { + if (isLambdaDefinitionPresent(lambdaApiAction)) { + executeGenericLambda(lambdaApiAction, lambadaData) + return + } when (lambdaApiAction.lambdaType) { LambdaType.CANCEL_VKYC.name -> { (bridge as? VkycLambdaBridge)?.cancelVKYCCall(lambdaApiAction) diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/models/lambdamodels/LambdaEventDetails.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/models/lambdamodels/LambdaEventDetails.kt new file mode 100644 index 0000000000..a50692d3d7 --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/models/lambdamodels/LambdaEventDetails.kt @@ -0,0 +1,23 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.models.lambdamodels + +import com.navi.ap.common.lambda.handler.LambdaHandler +import com.navi.ap.network.retrofit.ApRepoResult +import com.navi.common.uitron.model.LambdaEventData +import com.navi.common.uitron.model.action.LambdaApiAction +import kotlinx.coroutines.Job + +data class LambdaEventDetails( + val lambdaEventData: LambdaEventData?, + val lambdaApiAction: LambdaApiAction, + val resolvedValues: MutableMap, + val coroutineJobs: HashMap, + val lambdaResponse: ApRepoResult = ApRepoResult(), + val lambdaHandler: LambdaHandler +) diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/serializer/LambdaEventSerializer.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/serializer/LambdaEventSerializer.kt new file mode 100644 index 0000000000..8783227298 --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/common/serializer/LambdaEventSerializer.kt @@ -0,0 +1,59 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.common.serializer + +import com.google.gson.JsonElement +import com.google.gson.JsonSerializationContext +import com.google.gson.JsonSerializer +import com.navi.ap.common.lambda.verticals.generic.event.CancelCoroutineJobEvent +import com.navi.ap.common.lambda.verticals.generic.event.CustomBanksDataFilterHandlingEvent +import com.navi.ap.common.lambda.verticals.generic.event.DelayEvent +import com.navi.ap.common.lambda.verticals.generic.event.FailureActionEvent +import com.navi.ap.common.lambda.verticals.generic.event.PreExecutionActionEvent +import com.navi.ap.common.lambda.verticals.generic.event.ReturnPastApiResponseEvent +import com.navi.ap.common.lambda.verticals.generic.event.SetClonedScreenDefinitionStateEvent +import com.navi.ap.common.lambda.verticals.generic.event.SuccessActionEvent +import com.navi.ap.common.lambda.verticals.generic.event.TriggerApiEvent +import com.navi.ap.common.lambda.verticals.generic.event.UpdateAndTriggerSuccessActionEvent +import com.navi.ap.common.lambda.verticals.generic.event.UpdateScreenDefinitionEvent +import com.navi.common.uitron.model.LambdaAppEventType +import com.navi.common.uitron.model.LambdaEventData +import java.lang.reflect.Type + +class LambdaEventSerializer : JsonSerializer { + override fun serialize( + src: LambdaEventData?, + typeOfSrc: Type?, + context: JsonSerializationContext? + ): JsonElement? { + return when (src?.eventType) { + LambdaAppEventType.CANCEL_COROUTINE_JOB.name -> + context?.serialize(src, CancelCoroutineJobEvent::class.java) + LambdaAppEventType.PRE_EXECUTION_ACTION.name -> + context?.serialize(src, PreExecutionActionEvent::class.java) + LambdaAppEventType.TRIGGER_API.name -> + context?.serialize(src, TriggerApiEvent::class.java) + LambdaAppEventType.RETURN_PAST_API_RESPONSE.name -> + context?.serialize(src, ReturnPastApiResponseEvent::class.java) + LambdaAppEventType.SUCCESS_ACTION.name -> + context?.serialize(src, SuccessActionEvent::class.java) + LambdaAppEventType.FAILURE_ACTION.name -> + context?.serialize(src, FailureActionEvent::class.java) + LambdaAppEventType.DELAY.name -> context?.serialize(src, DelayEvent::class.java) + LambdaAppEventType.UPDATE_AND_TRIGGER_SUCCESS_ACTION.name -> + context?.serialize(src, UpdateAndTriggerSuccessActionEvent::class.java) + LambdaAppEventType.UPDATE_SCREEN_DEFINITION.name -> + context?.serialize(src, UpdateScreenDefinitionEvent::class.java) + LambdaAppEventType.SET_CLONED_SCREEN_DEFINITION_STATE.name -> + context?.serialize(src, SetClonedScreenDefinitionStateEvent::class.java) + LambdaAppEventType.CUSTOM_BANKS_DATA_FILTER_HANDLING.name -> + context?.serialize(src, CustomBanksDataFilterHandlingEvent::class.java) + else -> null + } + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/di/EntryPoints.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/di/EntryPoints.kt index fcf9dcb6ca..5b42c45677 100644 --- a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/di/EntryPoints.kt +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/di/EntryPoints.kt @@ -8,6 +8,7 @@ package com.navi.ap.di import com.navi.ap.common.lambda.verticals.coins.CoinLambdaRepository +import com.navi.ap.common.lambda.verticals.generic.GenericLambdaRepository import com.navi.ap.common.lambda.verticals.personalloan.PLLambdaRepository import com.navi.ap.common.usecase.UploadImageToAWSUseCase import dagger.hilt.EntryPoint @@ -28,6 +29,12 @@ class EntryPoints { fun getCoinLambdaRepository(): CoinLambdaRepository } + @EntryPoint + @InstallIn(SingletonComponent::class) + interface GenericLambdaRepositoryEntryPoint { + fun getGenericLambdaRepository(): GenericLambdaRepository + } + @EntryPoint @InstallIn(SingletonComponent::class) interface UploadImageToAWSUseCaseEntryPoint { diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/network/di/APNetworkModule.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/network/di/APNetworkModule.kt index a4f6d13f2a..06ccfbbdfd 100644 --- a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/network/di/APNetworkModule.kt +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/network/di/APNetworkModule.kt @@ -11,6 +11,7 @@ import com.google.gson.Gson import com.google.gson.GsonBuilder import com.navi.ap.common.serializer.ApUiTronActionSerializer import com.navi.ap.common.serializer.CustomUiTronDataSerializer +import com.navi.ap.common.serializer.LambdaEventSerializer import com.navi.ap.di.APGsonDeserializer import com.navi.ap.di.APGsonSerializer import com.navi.ap.network.retrofit.NaviApHttpClient @@ -20,6 +21,7 @@ import com.navi.ap.utils.registerPLSpecificDeSerializers import com.navi.common.CommonLibManager import com.navi.common.model.ModuleNameV2 import com.navi.common.network.converter.EmptyBodyHandlingConverterFactory +import com.navi.common.uitron.model.LambdaEventData import com.navi.common.uitron.model.action.ThirdPartySdkAction import com.navi.common.uitron.model.action.UploadDataConfig import com.navi.common.uitron.serializer.AnySerializer @@ -79,6 +81,7 @@ object APNetworkModule { ) .registerTypeAdapter(ThirdPartySdkAction::class.java, UiTronSDKActionSerializer()) .registerTypeAdapter(Any::class.java, AnySerializer()) + .registerTypeAdapter(LambdaEventData::class.java, LambdaEventSerializer()) .create() @Provides diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/network/retrofit/service/APRetrofitService.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/network/retrofit/service/APRetrofitService.kt index 9a3b2c8490..674ef89bf2 100644 --- a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/network/retrofit/service/APRetrofitService.kt +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/network/retrofit/service/APRetrofitService.kt @@ -23,7 +23,7 @@ import com.navi.common.utils.Constants.OS_ANDROID import retrofit2.Response import retrofit2.http.* -interface APRetrofitService : PlLambdaService, CoinsLambdaService { +interface APRetrofitService : PlLambdaService, CoinsLambdaService, GenericLambdaService { @POST("/arc-warden/api/v3/application/{applicationId}/screen/{screenId}") suspend fun fetchScreenDefinition( @Path("applicationId") applicationId: String, diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/network/retrofit/service/GenericLambdaService.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/network/retrofit/service/GenericLambdaService.kt new file mode 100644 index 0000000000..eaf1d78525 --- /dev/null +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/network/retrofit/service/GenericLambdaService.kt @@ -0,0 +1,55 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.ap.network.retrofit.service + +import com.navi.common.network.models.GenericResponse +import retrofit2.Response +import retrofit2.http.Body +import retrofit2.http.DELETE +import retrofit2.http.GET +import retrofit2.http.HeaderMap +import retrofit2.http.PATCH +import retrofit2.http.POST +import retrofit2.http.PUT +import retrofit2.http.Url + +interface GenericLambdaService { + + @GET + suspend fun getRequest( + @Url url: String, + @HeaderMap headers: Map + ): Response> + + @POST + suspend fun postRequest( + @Url url: String, + @HeaderMap headers: Map, + @Body requestBody: Any + ): Response> + + @PATCH + suspend fun patchRequest( + @Url url: String, + @HeaderMap headers: Map, + @Body requestBody: Any + ): Response> + + @DELETE + suspend fun deleteRequest( + @Url url: String, + @HeaderMap headers: Map + ): Response> + + @PUT + suspend fun putRequest( + @Url url: String, + @HeaderMap headers: Map, + @Body body: Any, + ): Response> +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/Ext.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/Ext.kt index 7bc3ffee9c..a9bedd01f3 100644 --- a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/Ext.kt +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/Ext.kt @@ -12,6 +12,7 @@ import com.google.gson.reflect.TypeToken import com.navi.ap.common.deserializer.ApUiTronActionDeserializer import com.navi.ap.common.deserializer.CustomUiTronDataDeserializer import com.navi.ap.common.deserializer.KYCSDKSettingsDataDeserializer +import com.navi.ap.common.deserializer.LambdaEventDeserializer import com.navi.ap.common.sdk.model.KycSdkSettingData import com.navi.ap.common.viewmodel.ApplicationPlatformVM import com.navi.ap.utils.constants.APP_FROM_SCREEN_ID @@ -20,6 +21,7 @@ import com.navi.ap.utils.constants.DEFAULT_SOURCE_SCREEN import com.navi.base.model.CtaData import com.navi.base.utils.EMPTY import com.navi.base.utils.orElse +import com.navi.common.uitron.model.LambdaEventData import com.navi.common.utils.log import com.navi.common.utils.registerUiTronDeSerializers import com.navi.payment.model.clientmodels.PaymentEvent @@ -97,6 +99,7 @@ fun GsonBuilder.registerApUiTronDeSerializers(): GsonBuilder { return registerUiTronDeSerializers().apply { registerTypeAdapter(UiTronData::class.java, CustomUiTronDataDeserializer()) registerTypeAdapter(UiTronAction::class.java, ApUiTronActionDeserializer()) + registerTypeAdapter(LambdaEventData::class.java, LambdaEventDeserializer()) } } diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/Utils.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/Utils.kt index 3bdf187f04..32565f410f 100644 --- a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/Utils.kt +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/Utils.kt @@ -27,14 +27,19 @@ import com.navi.ap.common.ui.ApplicationPlatformActivity import com.navi.ap.network.di.APNetworkModule.providesDeserializer import com.navi.ap.network.di.APNetworkModule.providesSerializer import com.navi.ap.screens.genericscreen.vm.ApGenericScreenVM +import com.navi.ap.utils.constants.CODE import com.navi.ap.utils.constants.DEFAULT_SCREEN_STATE_ID import com.navi.ap.utils.constants.DEFAULT_SOURCE_SCREEN +import com.navi.ap.utils.constants.DOT_SDK_DOT import com.navi.ap.utils.constants.JOURNEY_SOURCE +import com.navi.ap.utils.constants.KEY_PAYMENT_GATEWAY_EVENT_NAME +import com.navi.ap.utils.constants.KEY_PAYMENT_SDK_VERSION import com.navi.ap.utils.constants.LATITUDE import com.navi.ap.utils.constants.LAYOUT_ID import com.navi.ap.utils.constants.LONGITUDE import com.navi.ap.utils.constants.METHOD_NAME import com.navi.ap.utils.constants.PARENT +import com.navi.ap.utils.constants.PAYMENT_DOT_GATEWAY_DOT import com.navi.ap.utils.constants.SOURCE_AP import com.navi.ap.utils.constants.VIEW_ID import com.navi.ap.utils.constants.WIDGET_ID @@ -47,6 +52,8 @@ import com.navi.common.utils.CommonUtils import com.navi.common.utils.EMPTY import com.navi.common.utils.getDeviceData import com.navi.common.utils.log +import com.navi.payment.utils.Constants +import com.navi.payment.utils.PaymentAnalytics.PROVIDER import com.navi.uitron.model.UiTronResponse import com.navi.uitron.utils.getInputId import com.navi.uitron.utils.isNull @@ -177,6 +184,15 @@ fun getResolvedFieldValue( val output: String? = handle[name] map[item.sourceProperty.orEmpty()] = "${output.orEmpty()}$valueSuffix" } + SourceType.DEVICE_PROPERTY.name -> { + val value = + getDeviceData( + sourceProperty = item.sourceProperty.orEmpty(), + context = CommonLibManager.application.applicationContext, + additionalValues = item.additionalParameters + ) + map[name] = value + } SourceType.PRE_DEFINED.name -> { map[name] = "${item.value.orEmpty()}$valueSuffix" } @@ -185,14 +201,16 @@ fun getResolvedFieldValue( val output = readJsonPath(obj.toJson(), item.jsonPath.orEmpty()) map[item.sourceProperty.orEmpty()] = "$output$valueSuffix" } - SourceType.DEVICE_PROPERTY.name -> { - val value = - getDeviceData( - sourceProperty = item.sourceProperty.orEmpty(), - context = CommonLibManager.application.applicationContext, - additionalValues = item.additionalParameters - ) - map[item.name.orEmpty()] = value + SourceType.CONSTANTS.name -> { + map[name] = + when (item.sourceProperty) { + KEY_PAYMENT_SDK_VERSION -> Constants.PAYMENT_SDK_VERSION + else -> EMPTY + } + } + SourceType.CUSTOM_LOGIC.name -> { + val value = getCustomFieldData(item.sourceProperty.orEmpty(), map) + map[name] = value } else -> Unit } @@ -323,3 +341,38 @@ fun buildFillParametersUsingWidgetOutput( ) } } + +fun getCustomFieldData(sourceProperty: String, map: MutableMap? = null): String { + return when (sourceProperty) { + KEY_PAYMENT_GATEWAY_EVENT_NAME -> { + getPaymentGatewayEventName(map?.get(CODE).toString(), map?.get(PROVIDER).toString()) + } + else -> EMPTY + } +} + +private fun getPaymentGatewayEventName(code: String, provider: String): String { + return "$PAYMENT_DOT_GATEWAY_DOT$provider$DOT_SDK_DOT$code" +} + +fun injectValuesInAStringWithPlaceHolders(text: String, dataObj: Any): String { + val placeholders = text.split("{").drop(1).map { it.split("}")[0] } + var result = text + + placeholders.forEach { placeholder -> + val value = (getValueAtJsonPath(dataObj, placeholder) ?: EMPTY).toString() + result = result.replace("{$placeholder}", value) + } + + return result +} + +fun getValueAtJsonPath(dataObj: Any, jsonPath: String): Any? { + return try { + val dataObject = JSONObject(dataObj.toJson()) + readJsonPath(dataObject.toString(), jsonPath) + } catch (e: Exception) { + e.log() + null + } +} diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/constants/ApConstants.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/constants/ApConstants.kt index 51cbd05665..36453bb5ae 100644 --- a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/constants/ApConstants.kt +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/constants/ApConstants.kt @@ -62,6 +62,7 @@ const val WIDGET_ID = "widgetId" const val PARENT = "parent" const val INVALID_IFSC_CODE = "INVALID_IFSC_CODE" const val SOURCE = "source" +const val EVENT = "event" val noLoaderScreenTypes: MutableSet = mutableSetOf( @@ -85,3 +86,7 @@ const val SELECTED_DATE_WITH_SUFFIX = "selectedDateWithSuffix" const val SELECTED_FORMATTED_DATE = "selectedFormattedDate" const val SHOW = "show" const val INVALID_PIN_CODE = "INVALID_PIN_CODE" +const val KEY_PAYMENT_SDK_VERSION = "KEY_PAYMENT_SDK_VERSION" +const val KEY_PAYMENT_GATEWAY_EVENT_NAME = "paymentGatewayEventName" +const val PAYMENT_DOT_GATEWAY_DOT = "payments.gateway." +const val DOT_SDK_DOT = ".sdk." diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/constants/EventConstant.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/constants/EventConstant.kt index d674dee8d6..6f49f71459 100644 --- a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/constants/EventConstant.kt +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/constants/EventConstant.kt @@ -62,3 +62,13 @@ const val DIGILOCKER = "digilocker" // HYPERVERGE PAN const val HYPERVERGE_PAN_CAPTURE_SUCCESS = "hyperverge_pan_capture_success" const val HYPERVERGE_PAN_CAPTURE_ERROR = "hyperverge_pan_capture_error" + +// GENERIC LAMBDA +const val GENERIC_LAMBDA_INIT = "generic_lambda_init" +const val GENERIC_LAMBDA_TRIGGER_PRE_LAUNCH = "generic_lambda_trigger_pre_launch" +const val GENERIC_LAMBDA_TRIGGER_POST_LAUNCH = "generic_lambda_trigger_post_launch" +const val GENERIC_LAMBDA_TRIGGER_API = "generic_lambda_trigger_api" +const val GENERIC_LAMBDA_PAST_API_RESPONSE = "generic_lambda_past_api_response" +const val GENERIC_LAMBDA_TRIGGER_OUT_OF_SCOPE = "generic_lambda_trigger_out_of_scope" +const val GENERIC_LAMBDA_TRIGGER_SCOPE = "generic_lambda_trigger_scope" +const val GENERIC_LAMBDA_HANDLE_LAMBDA_STATE = "generic_lambda_handle_lambda_state" diff --git a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/injector/PathInjector.kt b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/injector/PathInjector.kt index 5e601f3ea8..7921beb137 100644 --- a/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/injector/PathInjector.kt +++ b/android/application-platform/navi-ap/src/main/kotlin/com/navi/ap/utils/injector/PathInjector.kt @@ -13,6 +13,11 @@ import org.json.JSONArray import org.json.JSONObject class PathInjector : BasePathInjector() { + + companion object { + const val TAG = "PATH_INJECTOR" + } + override fun inject(currentObject: JSONObject, key: String, type: JSON_TYPE) { when (type) { JSON_TYPE.JSONArray -> { diff --git a/android/navi-common/src/main/java/com/navi/common/uitron/model/LambdaDefinition.kt b/android/navi-common/src/main/java/com/navi/common/uitron/model/LambdaDefinition.kt new file mode 100644 index 0000000000..0d5ddee6ee --- /dev/null +++ b/android/navi-common/src/main/java/com/navi/common/uitron/model/LambdaDefinition.kt @@ -0,0 +1,97 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.common.uitron.model + +import com.google.gson.annotations.SerializedName + +data class LambdaDefinition( + @SerializedName("id") val id: String? = null, + @SerializedName("name") val name: String? = null, + @SerializedName("implementation") val implementation: LambdaImplementation? = null, + @SerializedName("contract") val contract: LambdaContract? = null, + @SerializedName("namespace") val namespace: String? = null +) + +data class LambdaImplementation( + @SerializedName("workerType") val workerType: String? = null, + @SerializedName("conditions") + val conditions: LinkedHashMap? = null, + @SerializedName("preLaunchEvents") val preLaunchEvents: List? = null, + @SerializedName("postLaunchEvents") val postLaunchEvents: List? = null, + @SerializedName("request") val request: LambdaRequestConfig? = null, + @SerializedName("response") val response: Map? = null, + @SerializedName("apiTag") val apiTag: String? = null +) + +data class ConditionEvaluationState( + @SerializedName("success") val success: String? = null // success mvel expression +) + +data class LambdaRequestConfig( + @SerializedName("subUrl") val subUrl: String? = null, + @SerializedName("method") val method: String? = null, + @SerializedName("body") val body: Any? = null, + @SerializedName("headers") val headers: Map? = null +) + +data class LambdaResponse( + @SerializedName("success") val success: LambdaResponseConfig? = null, + @SerializedName("failure") val failure: LambdaResponseConfig? = null +) + +data class LambdaResponseConfig( + @SerializedName("lambdaState") val lambdaState: LambdaStateData? = null, + @SerializedName("appEvents") val appEvents: List? = null, + @SerializedName("handleConfig") val handleConfig: List? = null +) + +open class LambdaStateData(@SerializedName("stateType") val stateType: String? = null) + +open class LambdaEventData(@SerializedName("eventType") val eventType: String? = null) + +data class LambdaResponseInjectionField( + @SerializedName("key") val key: String? = null, // resolved value key + @SerializedName("preDefinedValue") val preDefinedValue: Any? = null, // pre defined value + @SerializedName("jsonPath") val jsonPath: String? = null // response data json path +) + +data class LambdaContract( + @SerializedName("input") val input: Map? = null +) + +data class LambdaContractInput(@SerializedName("isRequired") val isRequired: Boolean? = null) + +enum class ApiRequestType { + GET, + POST, + PATCH, + PUT, + DELETE +} + +enum class LambdaStateType { + LOADING, + SUCCESS, + ERROR, + CUSTOM_ERROR, + NOTHING +} + +enum class LambdaAppEventType { + CANCEL_COROUTINE_JOB, + PRE_EXECUTION_ACTION, + TRIGGER_API, + RETURN_PAST_API_RESPONSE, + SUCCESS_ACTION, + FAILURE_ACTION, + DELAY, + UPDATE_AND_TRIGGER_SUCCESS_ACTION, + UPDATE_SCREEN_DEFINITION, + SET_CLONED_SCREEN_DEFINITION_STATE, + CUSTOM_BANKS_DATA_FILTER_HANDLING +} diff --git a/android/navi-common/src/main/java/com/navi/common/uitron/model/action/TriggerApiActions.kt b/android/navi-common/src/main/java/com/navi/common/uitron/model/action/TriggerApiActions.kt index d047c17193..e537233f62 100644 --- a/android/navi-common/src/main/java/com/navi/common/uitron/model/action/TriggerApiActions.kt +++ b/android/navi-common/src/main/java/com/navi/common/uitron/model/action/TriggerApiActions.kt @@ -10,6 +10,7 @@ package com.navi.common.uitron.model.action import android.os.Parcelable import com.google.gson.annotations.SerializedName import com.navi.base.model.LineItem +import com.navi.common.uitron.model.LambdaDefinition import com.navi.uitron.model.action.TriggerApiAction import com.navi.uitron.model.data.UiTronActionData import kotlinx.parcelize.Parcelize @@ -41,7 +42,8 @@ data class FillApiData( open class LambdaApiAction( @SerializedName("lambdaType") val lambdaType: String? = null, @SerializedName("preExecutionAction") val preExecutionAction: UiTronActionData? = null, - @SerializedName("fields") val fields: List? = null + @SerializedName("fields") val fields: List? = null, + @SerializedName("definition") var definition: LambdaDefinition? = null ) : TriggerApiAction() enum class ApiType { @@ -70,7 +72,9 @@ enum class SourceType { ZERO_TIMESTAMP, HANDLE, HANDLE_OBJECT, - USER_LOCATION + USER_LOCATION, + CONSTANTS, + CUSTOM_LOGIC } enum class ApiCallStrategyType {