-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SNAPSHOT dmvapp sample presentation layer
- Loading branch information
1 parent
e01d017
commit 98ebaca
Showing
27 changed files
with
473 additions
and
293 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 3 additions & 3 deletions
6
...on/src/main/kotlin/tech/coner/trailer/toolkit/presentation/adapter/LoadableItemAdapter.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 29 additions & 40 deletions
69
...esentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/BaseItemModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,76 +1,65 @@ | ||
package tech.coner.trailer.toolkit.presentation.model | ||
|
||
import kotlin.reflect.KProperty1 | ||
import kotlinx.coroutines.flow.Flow | ||
import kotlinx.coroutines.flow.MutableStateFlow | ||
import kotlinx.coroutines.flow.asStateFlow | ||
import kotlinx.coroutines.flow.map | ||
import kotlinx.coroutines.flow.update | ||
import tech.coner.trailer.toolkit.konstraints.CompositeConstraint | ||
import tech.coner.trailer.toolkit.konstraints.ConstraintViolationException | ||
import tech.coner.trailer.toolkit.validation.Feedback | ||
import tech.coner.trailer.toolkit.validation.ValidationResult | ||
import tech.coner.trailer.toolkit.validation.Validator | ||
|
||
abstract class BaseItemModel<I, C : CompositeConstraint<I>> : ItemModel<I> { | ||
abstract val constraints: C | ||
abstract class BaseItemModel<ITEM, VALIDATOR_CONTEXT, VALIDATOR_FEEDBACK> | ||
: ItemModel<ITEM, VALIDATOR_FEEDBACK> | ||
where VALIDATOR_FEEDBACK : Feedback { | ||
|
||
abstract val initialItem: I | ||
abstract val validator: Validator<VALIDATOR_CONTEXT, ITEM, VALIDATOR_FEEDBACK> | ||
abstract val validatorContext: VALIDATOR_CONTEXT | ||
|
||
abstract val initialItem: ITEM | ||
private val _itemFlow by lazy { MutableStateFlow(initialItem) } | ||
final override val itemFlow by lazy { _itemFlow.asStateFlow() } | ||
final override val item: I | ||
final override val item: ITEM | ||
get() = _itemFlow.value | ||
|
||
private val _pendingItemFlow by lazy { MutableStateFlow(initialItem) } | ||
final override val pendingItemFlow by lazy { _pendingItemFlow.asStateFlow() } | ||
final override var pendingItem: I | ||
final override var pendingItem: ITEM | ||
get() = pendingItemFlow.value | ||
set(value) = mutatePendingItem { value } | ||
private val _pendingItemValidationFlow by lazy { MutableStateFlow(emptyList<ValidationContent>()) } | ||
|
||
private val _pendingItemValidationFlow by lazy { | ||
MutableStateFlow<ValidationResult<ITEM, VALIDATOR_FEEDBACK>>( | ||
ValidationResult(emptyMap()) | ||
) | ||
} | ||
final override val pendingItemValidationFlow by lazy { _pendingItemValidationFlow.asStateFlow() } | ||
final override val pendingItemValidation get() = _pendingItemValidationFlow.value | ||
|
||
final override fun mutatePendingItem(forceValidate: Boolean?, mutatePendingItemFn: (I) -> I) { | ||
final override fun mutatePendingItem(forceValidate: Boolean?, mutatePendingItemFn: (ITEM) -> ITEM) { | ||
_pendingItemFlow.update { pending -> mutatePendingItemFn(pending) } | ||
if (forceValidate == true) { | ||
validate() | ||
} | ||
} | ||
|
||
override fun <P> validatedPropertyFlow(property: KProperty1<I, *>, fn: (I) -> P): Flow<Validated<P>> { | ||
val constraints = constraints.propertyConstraints[property] | ||
?: throw Exception("propertyConstraints does not contain any constraints for property: $property") | ||
return pendingItemFlow.map { item -> | ||
Validated( | ||
fn(item), | ||
constraints | ||
.mapNotNull { constraint -> constraint(item).exceptionOrNull() as ConstraintViolationException? } | ||
.map { Violation(it) } | ||
) | ||
} | ||
} | ||
|
||
final override val isPendingItemValid | ||
get() = _pendingItemValidationFlow.value.isValid() | ||
get() = _pendingItemValidationFlow.value.isValid | ||
|
||
final override val isPendingItemDirty | ||
get() = item != pendingItem | ||
|
||
final override fun validate(): List<ValidationContent> { | ||
return constraints.all | ||
.mapNotNull { it.invoke(pendingItem).exceptionOrNull() as? ConstraintViolationException } | ||
.map { ValidationContent.Error(it.message ?: "Invalid" /* TODO not hard-code english string */) } | ||
final override fun validate(): ValidationResult<ITEM, VALIDATOR_FEEDBACK> { | ||
return validator(validatorContext, pendingItem) | ||
.also { _pendingItemValidationFlow.value = it } | ||
} | ||
|
||
override fun commit(forceValidate: Boolean): Result<I> { | ||
if (forceValidate) { | ||
validate() | ||
.also { | ||
if (!it.isValid()) { | ||
return Result.failure(ModelNotReadyToCommitException()) | ||
} | ||
} | ||
override fun commit(requireValid: Boolean, successFn: (ITEM) -> Unit) { | ||
if (requireValid) { | ||
if (!validate().isValid) { | ||
return | ||
} | ||
} | ||
return pendingItem | ||
pendingItem | ||
.also { _itemFlow.value = it } | ||
.let { Result.success(it) } | ||
.also { successFn(it) } | ||
} | ||
} |
30 changes: 17 additions & 13 deletions
30
...n/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/ItemModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,27 @@ | ||
package tech.coner.trailer.toolkit.presentation.model | ||
|
||
import kotlin.reflect.KProperty1 | ||
import kotlinx.coroutines.flow.Flow | ||
import kotlinx.coroutines.flow.StateFlow | ||
import tech.coner.trailer.toolkit.validation.Feedback | ||
import tech.coner.trailer.toolkit.validation.ValidationResult | ||
|
||
interface ItemModel<ITEM, FEEDBACK : Feedback> : Model { | ||
val itemFlow: StateFlow<ITEM> | ||
val item: ITEM | ||
|
||
val pendingItemFlow: StateFlow<ITEM> | ||
var pendingItem: ITEM | ||
|
||
interface ItemModel<I> : Model { | ||
val itemFlow: StateFlow<I> | ||
val item: I | ||
val pendingItemFlow: StateFlow<I> | ||
var pendingItem: I | ||
val pendingItemValidationFlow: Flow<List<ValidationContent>> | ||
val pendingItemValidation: List<ValidationContent> | ||
val isPendingItemValid: Boolean | ||
val isPendingItemDirty: Boolean | ||
|
||
fun mutatePendingItem(forceValidate: Boolean? = null, mutatePendingItemFn: (I) -> I) | ||
fun <P> validatedPropertyFlow(property: KProperty1<I, *>, fn: (I) -> P): Flow<Validated<P>> | ||
val pendingItemValidationFlow: Flow<ValidationResult<ITEM, FEEDBACK>> | ||
val pendingItemValidation: ValidationResult<ITEM, FEEDBACK> | ||
|
||
val isPendingItemValid: Boolean | ||
|
||
fun mutatePendingItem(forceValidate: Boolean? = null, mutatePendingItemFn: (ITEM) -> ITEM) | ||
|
||
fun validate(): List<ValidationContent> | ||
fun validate(): ValidationResult<ITEM, FEEDBACK> | ||
|
||
fun commit(forceValidate: Boolean = true): Result<I> | ||
fun commit(requireValid: Boolean = true, successFn: (ITEM) -> Unit) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 0 additions & 5 deletions
5
...in/kotlin/tech/coner/trailer/toolkit/presentation/model/ModelNotReadyToCommitException.kt
This file was deleted.
Oops, something went wrong.
6 changes: 0 additions & 6 deletions
6
...src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/ModelValidationException.kt
This file was deleted.
Oops, something went wrong.
7 changes: 0 additions & 7 deletions
7
...n/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/Validated.kt
This file was deleted.
Oops, something went wrong.
28 changes: 0 additions & 28 deletions
28
...tation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/ValidationContent.kt
This file was deleted.
Oops, something went wrong.
5 changes: 0 additions & 5 deletions
5
...n/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/Violation.kt
This file was deleted.
Oops, something went wrong.
102 changes: 0 additions & 102 deletions
102
...on/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/BaseItemPresenter.kt
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.