Checks.kt

  1. package com.hexagonkt.core

  2. import kotlin.reflect.KProperty1

  3. fun <T : Any> T.requireNotBlank(field: KProperty1<T, CharSequence?>) {
  4.     val fieldValue = field.get(this)
  5.     require(fieldValue?.isNotBlank() ?: true) { "'${field.name}' cannot be blank" }
  6. }

  7. fun <T : Any> T.requireNotBlanks(field: KProperty1<T, Collection<CharSequence>?>) {
  8.     val fieldValue = field.get(this) ?: emptyList()
  9.     require(fieldValue.all { it.isNotBlank() }) { "'${field.name}' cannot contain blanks" }
  10. }

  11. fun <T : Any, N> T.requireGreater(field: KProperty1<T, Comparable<N>?>, min: N) {
  12.     val fieldValue = field.get(this)
  13.     require((fieldValue?.compareTo(min) ?: 1) > 0) {
  14.         "'${field.name}' must be greater than $min: $fieldValue"
  15.     }
  16. }

  17. fun <T : Any, N> T.requireGreaterOrEquals(field: KProperty1<T, Comparable<N>?>, min: N) {
  18.     val fieldValue = field.get(this)
  19.     require((fieldValue?.compareTo(min) ?: 0) >= 0) {
  20.         "'${field.name}' must be equals or greater than $min: $fieldValue"
  21.     }
  22. }

  23. fun <T : Any, N> T.requireLower(field: KProperty1<T, Comparable<N>?>, min: N) {
  24.     val fieldValue = field.get(this)
  25.     require((fieldValue?.compareTo(min) ?: -1) < 0) {
  26.         "'${field.name}' must be lower than $min: $fieldValue"
  27.     }
  28. }

  29. fun <T : Any, N> T.requireLowerOrEquals(field: KProperty1<T, Comparable<N>?>, min: N) {
  30.     val fieldValue = field.get(this)
  31.     require((fieldValue?.compareTo(min) ?: 0) <= 0) {
  32.         "'${field.name}' must be equals or lower than $min: $fieldValue"
  33.     }
  34. }

  35. fun <T : Any, N> T.requireGreater(field: KProperty1<T, Comparable<N>?>, field2: KProperty1<T, N?>) {
  36.     field2.get(this)?.let { requireGreater(field, it) }
  37. }

  38. fun <T : Any, N> T.requireGreaterOrEquals(
  39.     field: KProperty1<T, Comparable<N>?>,
  40.     field2: KProperty1<T, N?>
  41. ) {
  42.     field2.get(this)?.let { requireGreaterOrEquals(field, it) }
  43. }

  44. fun <T : Any, N> T.requireLower(field: KProperty1<T, Comparable<N>?>, field2: KProperty1<T, N?>) {
  45.     field2.get(this)?.let { requireLower(field, it) }
  46. }

  47. fun <T : Any, N> T.requireLowerOrEquals(
  48.     field: KProperty1<T, Comparable<N>?>,
  49.     field2: KProperty1<T, N?>
  50. ) {
  51.     field2.get(this)?.let { requireLowerOrEquals(field, it) }
  52. }

  53. /**
  54.  * Ensure a collection has a fixed number of elements.
  55.  *
  56.  * @receiver Collection which size will be checked.
  57.  * @param count Required number of elements.
  58.  * @return Receiver reference (to allow call chaining).
  59.  */
  60. fun <Z> Collection<Z>.checkSize(count: IntRange): Collection<Z> = this.apply {
  61.     check(size in count) { "$size items while expecting only $count element" }
  62. }

  63. /**
  64.  * Execute a list of code block collecting the exceptions they may throw, in case there is any
  65.  * error, it throws a [MultipleException] with all the thrown exceptions.
  66.  *
  67.  * @param message Error message.
  68.  * @param blocks Blocks of code executed and checked.
  69.  */
  70. fun check(message: String, vararg blocks: () -> Unit) {
  71.     val exceptions: List<Exception> = blocks.mapNotNull {
  72.         try {
  73.             it()
  74.             null
  75.         }
  76.         catch(e: Exception) {
  77.             e
  78.         }
  79.     }

  80.     if (exceptions.isNotEmpty())
  81.         throw MultipleException(message, exceptions)
  82. }