CommandInputHandler.kt
package de.pflugradts.passbird.application.commandhandling
import de.pflugradts.kotlinextensions.tryCatching
import de.pflugradts.passbird.application.InactivityTerminationRequestedException
import de.pflugradts.passbird.application.StdinTerminationRequestedException
import de.pflugradts.passbird.application.commandhandling.CommandType.Companion.resolveCommandTypeFrom
import de.pflugradts.passbird.application.commandhandling.command.NullCommand
import de.pflugradts.passbird.application.commandhandling.command.RepeatLastCommand
import de.pflugradts.passbird.application.commandhandling.command.base.Command
import de.pflugradts.passbird.application.commandhandling.factory.CommandFactory
import de.pflugradts.passbird.application.failure.CommandFailure
import de.pflugradts.passbird.application.failure.reportFailure
import de.pflugradts.passbird.domain.model.transfer.Input
class CommandInputHandler constructor(
private val commandBus: CommandBus,
private val commandFactory: CommandFactory,
private val rememberedCommandMemory: RememberedCommandMemory,
private val commandExecutionTracker: CommandExecutionTracker,
) : InputHandler {
override fun handleInput(input: Input) {
val originalInput = input.shell.copy()
commandExecutionTracker.begin()
val command = tryCatching {
commandFactory.construct(resolveCommandTypeFrom(input.command), input)
}.onFailure {
commandExecutionTracker.markFailure()
reportFailure(CommandFailure(it))
}.getOrNull()
val outcome = if (command == null) {
commandExecutionTracker.finish(CommandExecutionOutcome.FAILURE)
} else {
tryCatching {
commandBus.post(command)
commandExecutionTracker.finish(command.defaultOutcome())
}.onFailure { ex ->
if (ex is InactivityTerminationRequestedException || ex is StdinTerminationRequestedException) {
commandExecutionTracker.finish(CommandExecutionOutcome.FAILURE)
originalInput.scramble()
throw ex
}
commandExecutionTracker.markFailure()
reportFailure(CommandFailure(ex))
}.getOrNull() ?: commandExecutionTracker.finish(CommandExecutionOutcome.FAILURE)
}
if (outcome == CommandExecutionOutcome.SUCCESS && command !is RepeatLastCommand) {
rememberedCommandMemory.remember(originalInput)
} else {
originalInput.scramble()
}
}
}
private fun Command.defaultOutcome() = if (this is NullCommand) {
CommandExecutionOutcome.FAILURE
} else {
CommandExecutionOutcome.SUCCESS
}