Checks.kt

  1. package com.hexagontk.helpers

  2. import com.hexagontk.core.MultipleException
  3. import kotlin.reflect.KProperty1

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

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

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

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

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

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

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

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

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

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

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

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

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