ExceptionHandler.kt
- package com.hexagontk.handlers
- import kotlin.reflect.KClass
- import kotlin.reflect.cast
- /**
- * After handlers are executed even if a filter don't call next handler (if after was added before
- * filter).
- *
- * After handlers' filters are always true because they are meant to be evaluated on the **return**.
- * If they are not called in first place, they won't be executed on the return of the next handler.
- * Their filter is evaluated after the `next` call, not before.
- */
- class ExceptionHandler<T : Any, E : Exception>(
- val exception: KClass<E>,
- val exceptionCallback: (Context<T>, E) -> Context<T>,
- ) : Handler<T> {
- internal companion object {
- fun <T : Exception> castException(exception: Exception?, exceptionClass: KClass<T>): T =
- exception
- ?.let { exceptionClass.cast(exception) }
- ?: error("Exception 'null' or incorrect type")
- }
- override val predicate: (Context<T>) -> Boolean = { true }
- val callback: (Context<T>) -> Context<T> = { context ->
- exceptionCallback(context, castException(context.exception, exception))
- .with(exception = null)
- }
- override fun process(context: Context<T>): Context<T> {
- val next = context.next().with(predicate = ::afterPredicate)
- return try {
- if (afterPredicate(next)) callback(next)
- else next
- }
- catch (e: Exception) {
- next.with(exception = e)
- }
- }
- private fun afterPredicate(context: Context<T>): Boolean {
- val exceptionClass = context.exception?.javaClass ?: return false
- return exception.java.isAssignableFrom(exceptionClass)
- }
- }