Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vl 6035 #76

Open
wants to merge 6 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions VCL/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ android {
defaultConfig {
minSdk 24
targetSdk 33
versionName "1.23.0"
versionCode 119
versionName "1.24.0"
versionCode 120
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* Created by Michael Avoyan on 25/10/2023.
*
* Copyright 2022 Velocity Career Labs inc.
* SPDX-License-Identifier: Apache-2.0
*/

package io.velocitycareerlabs.api.entities

import org.json.JSONObject

data class VCLServiceTypeDynamic(
val payload: JSONObject
) {
val serviceType: String get() = payload.optString(KeyServiceType)
val serviceCategory: String get() = payload.optString(KeyServiceCategory)
val notary: Boolean get() = payload.optBoolean(KeyNotary)
val credentialGroup: String get() = payload.optString(KeyCredentialGroup)

companion object CodingKeys {
const val KeyServiceType = "serviceType"
const val KeyServiceCategory = "serviceCategory"
const val KeyNotary = "notary"
const val KeyCredentialGroup = "credentialGroup"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Created by Michael Avoyan on 25/10/2023.
*
* Copyright 2022 Velocity Career Labs inc.
* SPDX-License-Identifier: Apache-2.0
*/

package io.velocitycareerlabs.api.entities

data class VCLServiceTypesDynamic(val all: List<VCLServiceTypeDynamic>) {
companion object CodingKeys {
const val KeyServiceTypes = "serviceTypes"
}
}
20 changes: 19 additions & 1 deletion VCL/src/main/java/io/velocitycareerlabs/impl/VCLImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import io.velocitycareerlabs.api.entities.handleResult
import io.velocitycareerlabs.api.entities.initialization.VCLInitializationDescriptor
import io.velocitycareerlabs.impl.domain.models.CountriesModel
import io.velocitycareerlabs.impl.domain.models.CredentialTypesModel
import io.velocitycareerlabs.impl.domain.models.ServiceTypesModel
import io.velocitycareerlabs.impl.domain.usecases.CredentialManifestUseCase
import io.velocitycareerlabs.impl.domain.usecases.CredentialTypesUIFormSchemaUseCase
import io.velocitycareerlabs.impl.domain.usecases.ExchangeProgressUseCase
Expand All @@ -37,13 +38,14 @@ internal class VCLImpl: VCL {
companion object {
val TAG = VCLImpl::class.simpleName

private const val ModelsToInitializeAmount = 3
private const val ModelsToInitializeAmount = 4
}
private lateinit var initializationDescriptor: VCLInitializationDescriptor

private lateinit var credentialTypesModel: CredentialTypesModel
private lateinit var credentialTypeSchemasModel: CredentialTypeSchemasModel
private lateinit var countriesModel: CountriesModel
private lateinit var serviceTypesModel: ServiceTypesModel

private lateinit var presentationRequestUseCase: PresentationRequestUseCase
private lateinit var presentationSubmissionUseCase: PresentationSubmissionUseCase
Expand Down Expand Up @@ -161,6 +163,9 @@ internal class VCLImpl: VCL {
countriesModel =
VclBlocksProvider.provideCountriesModel(context)

serviceTypesModel =
VclBlocksProvider.provideServiceTypesModel(context)

countriesModel.initialize(cacheSequence) { result ->
result.handleResult(
{
Expand All @@ -172,6 +177,7 @@ internal class VCLImpl: VCL {
completionHandler(context, successHandler, errorHandler)
})
}

credentialTypesModel.initialize(cacheSequence) { result ->
result.handleResult(
{
Expand Down Expand Up @@ -209,6 +215,18 @@ internal class VCLImpl: VCL {
}
})
}

serviceTypesModel.initialize(cacheSequence) { result ->
result.handleResult(
{
if (initializationWatcher.onInitializedModel(null))
completionHandler(context, successHandler, errorHandler)
},
{ error ->
if (initializationWatcher.onInitializedModel(error))
completionHandler(context, successHandler, errorHandler)
})
}
}

private fun initGlobalConfigurations() {
Expand Down
12 changes: 12 additions & 0 deletions VCL/src/main/java/io/velocitycareerlabs/impl/VclBlocksProvider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,18 @@ internal object VclBlocksProvider {
)
)

@Throws(VCLError::class)
fun provideServiceTypesModel(context: Context): ServiceTypesModel =
ServiceTypesModelImpl(
ServiceTypesUseCaseImpl(
ServiceTypesRepositoryImpl(
NetworkServiceImpl(),
CacheServiceImpl(context)
),
ExecutorImpl()
)
)

@Throws(VCLError::class)
fun providePresentationRequestUseCase(
context: Context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@ internal class CacheServiceImpl(
private const val MODE = Context.MODE_PRIVATE

internal const val KEY_CACHE_SEQUENCE_COUNTRIES = "KEY_CACHE_SEQUENCE_COUNTRIES"
internal const val KEY_CACHE_SEQUENCE_CREDENTIAL_TYPES = "KEY_CACHE_SEQUENCE_CREDENTIAL_TYPES"
internal const val KEY_CACHE_SEQUENCE_CREDENTIAL_TYPE_SCHEMA = "KEY_CACHE_SEQUENCE_CREDENTIAL_TYPE_SCHEMA"
internal const val KEY_CACHE_SEQUENCE_CREDENTIAL_TYPES =
"KEY_CACHE_SEQUENCE_CREDENTIAL_TYPES"
internal const val KEY_CACHE_SEQUENCE_CREDENTIAL_TYPE_SCHEMA =
"KEY_CACHE_SEQUENCE_CREDENTIAL_TYPE_SCHEMA"
internal const val KEY_CACHE_SEQUENCE_SERVICE_TYPES = "KEY_CACHE_SEQUENCE_CREDENTIAL_TYPES"
}

private var preferences: SharedPreferences = context.getSharedPreferences(NAME, MODE)

// an inline function to put variable and save it
Expand All @@ -53,6 +57,7 @@ internal class CacheServiceImpl(
setString(key, value)
setInt(KEY_CACHE_SEQUENCE_COUNTRIES, cacheSequence)
}

override fun isResetCacheCountries(cacheSequence: Int) =
getInt(KEY_CACHE_SEQUENCE_COUNTRIES) < cacheSequence

Expand All @@ -61,6 +66,7 @@ internal class CacheServiceImpl(
setString(key, value)
setInt(KEY_CACHE_SEQUENCE_CREDENTIAL_TYPES, cacheSequence)
}

override fun isResetCacheCredentialTypes(cacheSequence: Int) =
getInt(KEY_CACHE_SEQUENCE_CREDENTIAL_TYPES) < cacheSequence

Expand All @@ -69,6 +75,16 @@ internal class CacheServiceImpl(
setString(key, value)
setInt(KEY_CACHE_SEQUENCE_CREDENTIAL_TYPE_SCHEMA, cacheSequence)
}

override fun isResetCacheCredentialTypeSchema(cacheSequence: Int) =
getInt(KEY_CACHE_SEQUENCE_CREDENTIAL_TYPE_SCHEMA) < cacheSequence

override fun getServiceTypes(key: String) = getString(key)
override fun setServiceTypes(key: String, value: String, cacheSequence: Int) {
setString(key, value)
setInt(KEY_CACHE_SEQUENCE_SERVICE_TYPES, cacheSequence)
}

override fun isResetCacheServiceTypes(cacheSequence: Int) =
getInt(KEY_CACHE_SEQUENCE_SERVICE_TYPES) < cacheSequence
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Created by Michael Avoyan on 25/10/2023.
*
* Copyright 2022 Velocity Career Labs inc.
* SPDX-License-Identifier: Apache-2.0
*/

package io.velocitycareerlabs.impl.data.models

import io.velocitycareerlabs.api.entities.VCLResult
import io.velocitycareerlabs.api.entities.VCLServiceTypesDynamic
import io.velocitycareerlabs.api.entities.data
import io.velocitycareerlabs.api.entities.handleResult
import io.velocitycareerlabs.impl.domain.models.ServiceTypesModel
import io.velocitycareerlabs.impl.domain.usecases.ServiceTypesUseCase

internal class ServiceTypesModelImpl(
private val serviceTypesUseCase: ServiceTypesUseCase
): ServiceTypesModel {

override var data: VCLServiceTypesDynamic? = null

override fun initialize(
cacheSequence: Int,
completionBlock: (VCLResult<VCLServiceTypesDynamic>) -> Unit
) {
serviceTypesUseCase.getServiceTypes(cacheSequence) { result ->
result.handleResult({ data = result.data }, { })
completionBlock(result)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/**
* Created by Michael Avoyan on 25/10/2023.
*
* Copyright 2022 Velocity Career Labs inc.
* SPDX-License-Identifier: Apache-2.0
*/

package io.velocitycareerlabs.impl.data.repositories

import io.velocitycareerlabs.api.entities.VCLResult
import io.velocitycareerlabs.api.entities.VCLServiceType
import io.velocitycareerlabs.api.entities.VCLServiceTypeDynamic
import io.velocitycareerlabs.api.entities.VCLServiceTypesDynamic
import io.velocitycareerlabs.api.entities.error.VCLError
import io.velocitycareerlabs.api.entities.handleResult
import io.velocitycareerlabs.impl.data.infrastructure.network.Request
import io.velocitycareerlabs.impl.domain.infrastructure.db.CacheService
import io.velocitycareerlabs.impl.domain.infrastructure.network.NetworkService
import io.velocitycareerlabs.impl.domain.repositories.ServiceTypesRepository
import io.velocitycareerlabs.impl.extensions.toJsonArray
import io.velocitycareerlabs.impl.extensions.toJsonObject
import org.json.JSONArray
import org.json.JSONObject
import java.lang.Exception

internal class ServiceTypesRepositoryImpl(
private val networkService: NetworkService,
private val cacheService: CacheService
): ServiceTypesRepository {
override fun getServiceTypes(
cacheSequence: Int,
completionBlock: (VCLResult<VCLServiceTypesDynamic>) -> Unit
) {
val endpoint = Urls.ServiceTypes
if (cacheService.isResetCacheServiceTypes(cacheSequence)) {
fetchServiceTypes(endpoint, cacheSequence, completionBlock)
} else {
cacheService.getServiceTypes(endpoint)?.let { serviceTypes ->
parse(serviceTypes.toJsonObject())?.let {
completionBlock(VCLResult.Success(it))
} ?: run {
completionBlock(VCLResult.Failure(VCLError("Failed to parse $serviceTypes")))
}
} ?: run {
fetchServiceTypes(endpoint, cacheSequence, completionBlock)
}
}
}

private fun fetchServiceTypes(
endpoint: String,
cacheSequence: Int,
completionBlock: (VCLResult<VCLServiceTypesDynamic>) -> Unit
) {
networkService.sendRequest(
endpoint = endpoint,
contentType = Request.ContentTypeApplicationJson,
method = Request.HttpMethod.GET,
headers = listOf(Pair(HeaderKeys.XVnfProtocolVersion, HeaderValues.XVnfProtocolVersion)),
useCaches = true,
completionBlock = { result ->
result.handleResult(
{ serviceTypesResponse->
try {
cacheService.setServiceTypes(
endpoint,
serviceTypesResponse.payload,
cacheSequence
)
parse(serviceTypesResponse.payload.toJsonObject())?.let {
completionBlock(VCLResult.Success(it))
} ?: run {
completionBlock(VCLResult.Failure(VCLError("Failed to parse ${serviceTypesResponse.payload}")))
}
} catch (ex: Exception) {
completionBlock(VCLResult.Failure(VCLError(ex)))
}
},
{ error ->
completionBlock(VCLResult.Failure(error))
}
)
}
)
}

private fun parse(serviceTypesJsonObj: JSONObject?): VCLServiceTypesDynamic? {
serviceTypesJsonObj?.optJSONArray(VCLServiceTypesDynamic.KeyServiceTypes)?.let {
serviceTypesJsonArr ->
val serviceTypesArr = mutableListOf<VCLServiceTypeDynamic>()
for (i in 0 until (serviceTypesJsonArr.length())) {
serviceTypesJsonArr.optJSONObject(i)?.let { payload ->
serviceTypesArr.add(
VCLServiceTypeDynamic(payload)
)
}
}
return VCLServiceTypesDynamic(serviceTypesArr)
} ?: return null
}

companion object {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ internal class Urls {
}
private val BaseUrlRegistrar get() = "https://${EnvironmentPrefix}registrar.velocitynetwork.foundation"
// private val BaseUrlWalletApi get() = "https://${EnvironmentPrefix}walletapi.velocitycareerlabs.io"
val ServiceTypes get() = "$BaseUrlRegistrar/api/v0.6/service-types"
val CredentialTypes get() = "$BaseUrlRegistrar/api/v0.6/credential-types"
val CredentialTypeSchemas get() = "$BaseUrlRegistrar/schemas/"
val Countries get() = "$BaseUrlRegistrar/reference/countries"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* Created by Michael Avoyan on 25/10/2023.
*/

package io.velocitycareerlabs.impl.data.usecases

import io.velocitycareerlabs.api.entities.VCLResult
import io.velocitycareerlabs.api.entities.VCLServiceTypesDynamic
import io.velocitycareerlabs.impl.domain.infrastructure.executors.Executor
import io.velocitycareerlabs.impl.domain.repositories.ServiceTypesRepository
import io.velocitycareerlabs.impl.domain.usecases.ServiceTypesUseCase

internal class ServiceTypesUseCaseImpl(
private val serviceTypesRepository: ServiceTypesRepository,
private val executor: Executor
): ServiceTypesUseCase {
override fun getServiceTypes(
cacheSequence: Int,
completionBlock: (VCLResult<VCLServiceTypesDynamic>) -> Unit
) {
executor.runOnBackground {
serviceTypesRepository.getServiceTypes(cacheSequence) {
executor.runOnMain {
completionBlock(it)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ internal interface CacheService {
fun getCredentialTypeSchema(key: String): String?
fun setCredentialTypeSchema(key: String, value: String, cacheSequence: Int)
fun isResetCacheCredentialTypeSchema(cacheSequence: Int): Boolean

fun getServiceTypes(key: String): String?
fun setServiceTypes(key: String, value: String, cacheSequence: Int)
fun isResetCacheServiceTypes(cacheSequence: Int): Boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Created by Michael Avoyan on 25/10/2023.
*
* Copyright 2022 Velocity Career Labs inc.
* SPDX-License-Identifier: Apache-2.0
*/

package io.velocitycareerlabs.impl.domain.models

import io.velocitycareerlabs.api.entities.VCLServiceTypesDynamic

internal interface ServiceTypesModel: Model<VCLServiceTypesDynamic>, Initializable<VCLServiceTypesDynamic>
Loading
Loading