ExceptionHandler.kt

  1. package com.hexagonkt.handlers

  2. import kotlin.reflect.KClass

  3. /**
  4.  * After handlers are executed even if a filter don't call next handler (if after was added before
  5.  * filter).
  6.  *
  7.  * After handlers' filters are always true because they are meant to be evaluated on the **return**.
  8.  * If they are not called in first place, they won't be executed on the return of the next handler.
  9.  * Their filter is evaluated after the `next` call, not before.
  10.  */
  11. data class ExceptionHandler<T : Any, E : Exception>(
  12.     val exception: KClass<E>,
  13.     val clear: Boolean = true,
  14.     val exceptionCallback: (Context<T>, E) -> Context<T>,
  15. ) : Handler<T> {

  16.     override val predicate: (Context<T>) -> Boolean = { true }
  17.     override val callback: (Context<T>) -> Context<T> = { context ->
  18.         exceptionCallback(context, castException(context.exception, exception)).let {
  19.             if (clear) it.with(exception = null)
  20.             else it
  21.         }
  22.     }

  23.     override fun process(context: Context<T>): Context<T> {
  24.         val next = context.next().with(predicate = ::afterPredicate)
  25.         return try {
  26.             if (afterPredicate(next)) callback(next)
  27.             else next
  28.         }
  29.         catch (e: Exception) {
  30.             next.with(exception = e)
  31.         }
  32.     }

  33.     private fun afterPredicate(context: Context<T>): Boolean {
  34.         val exceptionClass = context.exception?.javaClass ?: return false
  35.         return exception.java.isAssignableFrom(exceptionClass)
  36.     }
  37. }