Checks.kt
package com.hexagonkt.core
import kotlin.reflect.KProperty1
fun <T : Any> T.requireNotBlank(field: KProperty1<T, CharSequence?>) {
val fieldValue = field.get(this)
require(fieldValue?.isNotBlank() ?: true) { "'${field.name}' cannot be blank" }
}
fun <T : Any> T.requireNotBlanks(field: KProperty1<T, Collection<CharSequence>?>) {
val fieldValue = field.get(this) ?: emptyList()
require(fieldValue.all { it.isNotBlank() }) { "'${field.name}' cannot contain blanks" }
}
fun <T : Any, N> T.requireGreater(field: KProperty1<T, Comparable<N>?>, min: N) {
val fieldValue = field.get(this)
require((fieldValue?.compareTo(min) ?: 1) > 0) {
"'${field.name}' must be greater than $min: $fieldValue"
}
}
fun <T : Any, N> T.requireGreaterOrEquals(field: KProperty1<T, Comparable<N>?>, min: N) {
val fieldValue = field.get(this)
require((fieldValue?.compareTo(min) ?: 0) >= 0) {
"'${field.name}' must be equals or greater than $min: $fieldValue"
}
}
fun <T : Any, N> T.requireLower(field: KProperty1<T, Comparable<N>?>, min: N) {
val fieldValue = field.get(this)
require((fieldValue?.compareTo(min) ?: -1) < 0) {
"'${field.name}' must be lower than $min: $fieldValue"
}
}
fun <T : Any, N> T.requireLowerOrEquals(field: KProperty1<T, Comparable<N>?>, min: N) {
val fieldValue = field.get(this)
require((fieldValue?.compareTo(min) ?: 0) <= 0) {
"'${field.name}' must be equals or lower than $min: $fieldValue"
}
}
fun <T : Any, N> T.requireGreater(field: KProperty1<T, Comparable<N>?>, field2: KProperty1<T, N?>) {
field2.get(this)?.let { requireGreater(field, it) }
}
fun <T : Any, N> T.requireGreaterOrEquals(
field: KProperty1<T, Comparable<N>?>,
field2: KProperty1<T, N?>
) {
field2.get(this)?.let { requireGreaterOrEquals(field, it) }
}
fun <T : Any, N> T.requireLower(field: KProperty1<T, Comparable<N>?>, field2: KProperty1<T, N?>) {
field2.get(this)?.let { requireLower(field, it) }
}
fun <T : Any, N> T.requireLowerOrEquals(
field: KProperty1<T, Comparable<N>?>,
field2: KProperty1<T, N?>
) {
field2.get(this)?.let { requireLowerOrEquals(field, it) }
}
/**
* Ensure a collection has a fixed number of elements.
*
* @receiver Collection which size will be checked.
* @param count Required number of elements.
* @return Receiver reference (to allow call chaining).
*/
fun <Z> Collection<Z>.checkSize(count: IntRange): Collection<Z> = this.apply {
check(size in count) { "$size items while expecting only $count element" }
}
/**
* Execute a list of code block collecting the exceptions they may throw, in case there is any
* error, it throws a [MultipleException] with all the thrown exceptions.
*
* @param message Error message.
* @param blocks Blocks of code executed and checked.
*/
fun check(message: String, vararg blocks: () -> Unit) {
val exceptions: List<Exception> = blocks.mapNotNull {
try {
it()
null
}
catch(e: Exception) {
e
}
}
if (exceptions.isNotEmpty())
throw MultipleException(message, exceptions)
}