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

M4l2 business models #18

Merged
merged 3 commits into from
Feb 5, 2025
Merged
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
14 changes: 14 additions & 0 deletions ok-marketplace-be/ok-marketplace-api-v1-mappers/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
plugins {
id("build-jvm")
}

group = rootProject.group
version = rootProject.version

dependencies {
implementation(kotlin("stdlib"))
implementation(project(":ok-marketplace-api-v1-jackson"))
implementation(project(":ok-marketplace-common"))

testImplementation(kotlin("test-junit"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package ru.otus.otuskotlin.marketplace.mappers.v1

import ru.otus.otuskotlin.marketplace.api.v1.models.*
import ru.otus.otuskotlin.marketplace.common.MkplContext
import ru.otus.otuskotlin.marketplace.common.models.*
import ru.otus.otuskotlin.marketplace.common.models.MkplWorkMode
import ru.otus.otuskotlin.marketplace.common.stubs.MkplStubs
import ru.otus.otuskotlin.marketplace.mappers.v1.exceptions.UnknownRequestClass

fun MkplContext.fromTransport(request: IRequest) = when (request) {
is AdCreateRequest -> fromTransport(request)
is AdReadRequest -> fromTransport(request)
is AdUpdateRequest -> fromTransport(request)
is AdDeleteRequest -> fromTransport(request)
is AdSearchRequest -> fromTransport(request)
is AdOffersRequest -> fromTransport(request)
else -> throw UnknownRequestClass(request.javaClass)
}

private fun String?.toAdId() = this?.let { MkplAdId(it) } ?: MkplAdId.NONE
private fun String?.toAdWithId() = MkplAd(id = this.toAdId())
private fun String?.toAdLock() = this?.let { MkplAdLock(it) } ?: MkplAdLock.NONE

private fun AdDebug?.transportToWorkMode(): MkplWorkMode = when (this?.mode) {
AdRequestDebugMode.PROD -> MkplWorkMode.PROD
AdRequestDebugMode.TEST -> MkplWorkMode.TEST
AdRequestDebugMode.STUB -> MkplWorkMode.STUB
null -> MkplWorkMode.PROD
}

private fun AdDebug?.transportToStubCase(): MkplStubs = when (this?.stub) {
AdRequestDebugStubs.SUCCESS -> MkplStubs.SUCCESS
AdRequestDebugStubs.NOT_FOUND -> MkplStubs.NOT_FOUND
AdRequestDebugStubs.BAD_ID -> MkplStubs.BAD_ID
AdRequestDebugStubs.BAD_TITLE -> MkplStubs.BAD_TITLE
AdRequestDebugStubs.BAD_DESCRIPTION -> MkplStubs.BAD_DESCRIPTION
AdRequestDebugStubs.BAD_VISIBILITY -> MkplStubs.BAD_VISIBILITY
AdRequestDebugStubs.CANNOT_DELETE -> MkplStubs.CANNOT_DELETE
AdRequestDebugStubs.BAD_SEARCH_STRING -> MkplStubs.BAD_SEARCH_STRING
null -> MkplStubs.NONE
}

fun MkplContext.fromTransport(request: AdCreateRequest) {
command = MkplCommand.CREATE
adRequest = request.ad?.toInternal() ?: MkplAd()
workMode = request.debug.transportToWorkMode()
stubCase = request.debug.transportToStubCase()
}

fun MkplContext.fromTransport(request: AdReadRequest) {
command = MkplCommand.READ
adRequest = request.ad.toInternal()
workMode = request.debug.transportToWorkMode()
stubCase = request.debug.transportToStubCase()
}

private fun AdReadObject?.toInternal(): MkplAd = if (this != null) {
MkplAd(id = id.toAdId())
} else {
MkplAd()
}


fun MkplContext.fromTransport(request: AdUpdateRequest) {
command = MkplCommand.UPDATE
adRequest = request.ad?.toInternal() ?: MkplAd()
workMode = request.debug.transportToWorkMode()
stubCase = request.debug.transportToStubCase()
}

fun MkplContext.fromTransport(request: AdDeleteRequest) {
command = MkplCommand.DELETE
adRequest = request.ad.toInternal()
workMode = request.debug.transportToWorkMode()
stubCase = request.debug.transportToStubCase()
}

private fun AdDeleteObject?.toInternal(): MkplAd = if (this != null) {
MkplAd(
id = id.toAdId(),
lock = lock.toAdLock(),
)
} else {
MkplAd()
}

fun MkplContext.fromTransport(request: AdSearchRequest) {
command = MkplCommand.SEARCH
adFilterRequest = request.adFilter.toInternal()
workMode = request.debug.transportToWorkMode()
stubCase = request.debug.transportToStubCase()
}

fun MkplContext.fromTransport(request: AdOffersRequest) {
command = MkplCommand.OFFERS
adRequest = request.ad?.id.toAdWithId()
workMode = request.debug.transportToWorkMode()
stubCase = request.debug.transportToStubCase()
}

private fun AdSearchFilter?.toInternal(): MkplAdFilter = MkplAdFilter(
searchString = this?.searchString ?: ""
)

private fun AdCreateObject.toInternal(): MkplAd = MkplAd(
title = this.title ?: "",
description = this.description ?: "",
adType = this.adType.fromTransport(),
visibility = this.visibility.fromTransport(),
)

private fun AdUpdateObject.toInternal(): MkplAd = MkplAd(
id = this.id.toAdId(),
title = this.title ?: "",
description = this.description ?: "",
adType = this.adType.fromTransport(),
visibility = this.visibility.fromTransport(),
lock = lock.toAdLock(),
)

private fun AdVisibility?.fromTransport(): MkplVisibility = when (this) {
AdVisibility.PUBLIC -> MkplVisibility.VISIBLE_PUBLIC
AdVisibility.OWNER_ONLY -> MkplVisibility.VISIBLE_TO_OWNER
AdVisibility.REGISTERED_ONLY -> MkplVisibility.VISIBLE_TO_GROUP
null -> MkplVisibility.NONE
}

private fun DealSide?.fromTransport(): MkplDealSide = when (this) {
DealSide.DEMAND -> MkplDealSide.DEMAND
DealSide.SUPPLY -> MkplDealSide.SUPPLY
null -> MkplDealSide.NONE
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package ru.otus.otuskotlin.marketplace.mappers.v1

import ru.otus.otuskotlin.marketplace.api.v1.models.*
import ru.otus.otuskotlin.marketplace.common.MkplContext
import ru.otus.otuskotlin.marketplace.common.exceptions.UnknownMkplCommand
import ru.otus.otuskotlin.marketplace.common.models.*

fun MkplContext.toTransportAd(): IResponse = when (val cmd = command) {
MkplCommand.CREATE -> toTransportCreate()
MkplCommand.READ -> toTransportRead()
MkplCommand.UPDATE -> toTransportUpdate()
MkplCommand.DELETE -> toTransportDelete()
MkplCommand.SEARCH -> toTransportSearch()
MkplCommand.OFFERS -> toTransportOffers()
MkplCommand.NONE -> throw UnknownMkplCommand(cmd)
}

fun MkplContext.toTransportCreate() = AdCreateResponse(
result = state.toResult(),
errors = errors.toTransportErrors(),
ad = adResponse.toTransportAd()
)

fun MkplContext.toTransportRead() = AdReadResponse(
result = state.toResult(),
errors = errors.toTransportErrors(),
ad = adResponse.toTransportAd()
)

fun MkplContext.toTransportUpdate() = AdUpdateResponse(
result = state.toResult(),
errors = errors.toTransportErrors(),
ad = adResponse.toTransportAd()
)

fun MkplContext.toTransportDelete() = AdDeleteResponse(
result = state.toResult(),
errors = errors.toTransportErrors(),
ad = adResponse.toTransportAd()
)

fun MkplContext.toTransportSearch() = AdSearchResponse(
result = state.toResult(),
errors = errors.toTransportErrors(),
ads = adsResponse.toTransportAd()
)

fun MkplContext.toTransportOffers() = AdOffersResponse(
result = state.toResult(),
errors = errors.toTransportErrors(),
ads = adsResponse.toTransportAd()
)

fun List<MkplAd>.toTransportAd(): List<AdResponseObject>? = this
.map { it.toTransportAd() }
.toList()
.takeIf { it.isNotEmpty() }

private fun MkplAd.toTransportAd(): AdResponseObject = AdResponseObject(
id = id.takeIf { it != MkplAdId.NONE }?.asString(),
title = title.takeIf { it.isNotBlank() },
description = description.takeIf { it.isNotBlank() },
ownerId = ownerId.takeIf { it != MkplUserId.NONE }?.asString(),
adType = adType.toTransportAd(),
visibility = visibility.toTransportAd(),
permissions = permissionsClient.toTransportAd(),
)

private fun Set<MkplAdPermissionClient>.toTransportAd(): Set<AdPermissions>? = this
.map { it.toTransportAd() }
.toSet()
.takeIf { it.isNotEmpty() }

private fun MkplAdPermissionClient.toTransportAd() = when (this) {
MkplAdPermissionClient.READ -> AdPermissions.READ
MkplAdPermissionClient.UPDATE -> AdPermissions.UPDATE
MkplAdPermissionClient.MAKE_VISIBLE_OWNER -> AdPermissions.MAKE_VISIBLE_OWN
MkplAdPermissionClient.MAKE_VISIBLE_GROUP -> AdPermissions.MAKE_VISIBLE_GROUP
MkplAdPermissionClient.MAKE_VISIBLE_PUBLIC -> AdPermissions.MAKE_VISIBLE_PUBLIC
MkplAdPermissionClient.DELETE -> AdPermissions.DELETE
}

private fun MkplVisibility.toTransportAd(): AdVisibility? = when (this) {
MkplVisibility.VISIBLE_PUBLIC -> AdVisibility.PUBLIC
MkplVisibility.VISIBLE_TO_GROUP -> AdVisibility.REGISTERED_ONLY
MkplVisibility.VISIBLE_TO_OWNER -> AdVisibility.OWNER_ONLY
MkplVisibility.NONE -> null
}

private fun MkplDealSide.toTransportAd(): DealSide? = when (this) {
MkplDealSide.DEMAND -> DealSide.DEMAND
MkplDealSide.SUPPLY -> DealSide.SUPPLY
MkplDealSide.NONE -> null
}

private fun List<MkplError>.toTransportErrors(): List<Error>? = this
.map { it.toTransportAd() }
.toList()
.takeIf { it.isNotEmpty() }

private fun MkplError.toTransportAd() = Error(
code = code.takeIf { it.isNotBlank() },
group = group.takeIf { it.isNotBlank() },
field = field.takeIf { it.isNotBlank() },
message = message.takeIf { it.isNotBlank() },
)

private fun MkplState.toResult(): ResponseResult? = when (this) {
MkplState.RUNNING -> ResponseResult.SUCCESS
MkplState.FAILING -> ResponseResult.ERROR
MkplState.FINISHING -> ResponseResult.SUCCESS
MkplState.NONE -> null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package ru.otus.otuskotlin.marketplace.mappers.v1.exceptions

class UnknownRequestClass(clazz: Class<*>) : RuntimeException("Class $clazz cannot be mapped to MkplContext")
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import org.junit.Test
import ru.otus.otuskotlin.marketplace.api.v1.models.*
import ru.otus.otuskotlin.marketplace.common.MkplContext
import ru.otus.otuskotlin.marketplace.common.models.*
import ru.otus.otuskotlin.marketplace.common.stubs.MkplStubs
import kotlin.test.assertEquals

class MapperTest {
@Test
fun fromTransport() {
val req = AdCreateRequest(
debug = AdDebug(
mode = AdRequestDebugMode.STUB,
stub = AdRequestDebugStubs.SUCCESS,
),
ad = AdCreateObject(
title = "title",
description = "desc",
adType = DealSide.DEMAND,
visibility = AdVisibility.PUBLIC,
),
)

val context = MkplContext()
context.fromTransport(req)

assertEquals(MkplStubs.SUCCESS, context.stubCase)
assertEquals(MkplWorkMode.STUB, context.workMode)
assertEquals("title", context.adRequest.title)
assertEquals(MkplVisibility.VISIBLE_PUBLIC, context.adRequest.visibility)
assertEquals(MkplDealSide.DEMAND, context.adRequest.adType)
}

@Test
fun toTransport() {
val context = MkplContext(
requestId = MkplRequestId("1234"),
command = MkplCommand.CREATE,
adResponse = MkplAd(
title = "title",
description = "desc",
adType = MkplDealSide.DEMAND,
visibility = MkplVisibility.VISIBLE_PUBLIC,
),
errors = mutableListOf(
MkplError(
code = "err",
group = "request",
field = "title",
message = "wrong title",
)
),
state = MkplState.RUNNING,
)

val req = context.toTransportAd() as AdCreateResponse

assertEquals("title", req.ad?.title)
assertEquals("desc", req.ad?.description)
assertEquals(AdVisibility.PUBLIC, req.ad?.visibility)
assertEquals(DealSide.DEMAND, req.ad?.adType)
assertEquals(1, req.errors?.size)
assertEquals("err", req.errors?.firstOrNull()?.code)
assertEquals("request", req.errors?.firstOrNull()?.group)
assertEquals("title", req.errors?.firstOrNull()?.field)
assertEquals("wrong title", req.errors?.firstOrNull()?.message)
}
}
Loading
Loading