ApplicationEventHandler.kt
package de.pflugradts.passbird.application.eventhandling
import de.pflugradts.passbird.application.UserInterfaceAdapterPort
import de.pflugradts.passbird.domain.model.ddd.DomainEvent
import de.pflugradts.passbird.domain.model.event.EggCreated
import de.pflugradts.passbird.domain.model.event.EggDiscarded
import de.pflugradts.passbird.domain.model.event.EggMoved
import de.pflugradts.passbird.domain.model.event.EggNotFound
import de.pflugradts.passbird.domain.model.event.EggRenamed
import de.pflugradts.passbird.domain.model.event.EggUpdated
import de.pflugradts.passbird.domain.model.event.EggsExported
import de.pflugradts.passbird.domain.model.event.EggsImported
import de.pflugradts.passbird.domain.model.event.NestCreated
import de.pflugradts.passbird.domain.model.event.NestDiscarded
import de.pflugradts.passbird.domain.model.event.ProteinCreated
import de.pflugradts.passbird.domain.model.event.ProteinDiscarded
import de.pflugradts.passbird.domain.model.event.ProteinUpdated
import de.pflugradts.passbird.domain.model.shell.EncryptedShell
import de.pflugradts.passbird.domain.model.shell.Shell.Companion.shellOf
import de.pflugradts.passbird.domain.model.transfer.Output.Companion.outputOf
import de.pflugradts.passbird.domain.model.transfer.OutputFormatting.EVENT_HANDLED
import de.pflugradts.passbird.domain.service.eventhandling.EventHandler
import de.pflugradts.passbird.domain.service.password.encryption.CryptoProvider
class ApplicationEventHandler constructor(
private val cryptoProvider: CryptoProvider,
private val userInterfaceAdapterPort: UserInterfaceAdapterPort,
) : EventHandler {
override val eventTypes: Set<Class<out DomainEvent>> = setOf(
EggCreated::class.java,
EggUpdated::class.java,
EggRenamed::class.java,
EggDiscarded::class.java,
EggMoved::class.java,
EggNotFound::class.java,
EggsExported::class.java,
EggsImported::class.java,
ProteinCreated::class.java,
ProteinUpdated::class.java,
ProteinDiscarded::class.java,
NestCreated::class.java,
NestDiscarded::class.java,
)
override fun handle(domainEvent: DomainEvent) {
when (domainEvent) {
is EggCreated -> handleEggCreated(domainEvent)
is EggUpdated -> handleEggUpdated(domainEvent)
is EggRenamed -> handleEggRenamed(domainEvent)
is EggDiscarded -> handleEggDiscarded(domainEvent)
is EggMoved -> handleEggMoved(domainEvent)
is EggNotFound -> handleEggNotFound(domainEvent)
is EggsExported -> handleEggsExported(domainEvent)
is EggsImported -> handleEggsImported(domainEvent)
is ProteinCreated -> handleProteinCreated(domainEvent)
is ProteinUpdated -> handleProteinUpdated(domainEvent)
is ProteinDiscarded -> handleProteinDiscarded(domainEvent)
is NestCreated -> handleNestCreated(domainEvent)
is NestDiscarded -> handleNestDiscarded(domainEvent)
}
}
private fun handleEggCreated(eggCreated: EggCreated) {
send("Egg '${decrypt(eggCreated.egg.viewEggId())}' successfully created.")
}
private fun handleEggUpdated(eggUpdated: EggUpdated) {
send("Egg '${decrypt(eggUpdated.egg.viewEggId())}' successfully updated.")
}
private fun handleEggRenamed(eggRenamed: EggRenamed) {
send("Egg '${decrypt(eggRenamed.egg.viewEggId())}' successfully renamed.")
}
private fun handleEggDiscarded(eggDiscarded: EggDiscarded) {
send("Egg '${decrypt(eggDiscarded.egg.viewEggId())}' successfully discarded.")
}
private fun handleEggMoved(eggMoved: EggMoved) {
send("Egg '${decrypt(eggMoved.egg.viewEggId())}' successfully moved to ${nestSlotText(eggMoved.egg.associatedNest().index())}.")
}
private fun handleEggNotFound(eggNotFound: EggNotFound) {
send("Egg '${eggNotFound.eggIdShell.asString()}' not found.")
userInterfaceAdapterPort.warningSound()
}
private fun handleEggsExported(eggsExported: EggsExported) {
send("${eggsExported.count} eggs successfully exported.")
}
private fun handleEggsImported(eggsImported: EggsImported) {
send("${eggsImported.count} eggs successfully imported.")
}
private fun handleProteinCreated(proteinCreated: ProteinCreated) {
val proteinType = decrypt(proteinCreated.protein.viewType())
val eggId = decrypt(proteinCreated.egg.viewEggId())
val msg = "Protein '$proteinType' for egg '$eggId' successfully created."
send(msg)
}
private fun handleProteinUpdated(proteinUpdated: ProteinUpdated) {
val oldProteinType = decrypt(proteinUpdated.oldProtein.viewType())
val newProteinType = decrypt(proteinUpdated.newProtein.viewType())
val eggId = decrypt(proteinUpdated.egg.viewEggId())
val msg = if (oldProteinType == newProteinType) {
"Protein '$oldProteinType' at slot ${proteinUpdated.slot.index()} for egg '$eggId' successfully updated."
} else {
"Protein for egg '$eggId' at slot ${proteinUpdated.slot.index()} successfully updated " +
"from '$oldProteinType' to '$newProteinType'."
}
send(msg)
}
private fun handleProteinDiscarded(proteinDiscarded: ProteinDiscarded) {
val proteinType = decrypt(proteinDiscarded.protein.viewType())
val eggId = decrypt(proteinDiscarded.egg.viewEggId())
val msg = "Protein '$proteinType' of egg '$eggId' successfully discarded."
send(msg)
}
private fun handleNestCreated(nestCreated: NestCreated) {
send("Nest '${nestCreated.nest.viewNestId().asString()}' successfully created.")
}
private fun handleNestDiscarded(nestDiscarded: NestDiscarded) {
send("Nest '${nestDiscarded.nest.viewNestId().asString()}' successfully discarded.")
}
private fun send(str: String) = userInterfaceAdapterPort.send(outputOf(shellOf(str), EVENT_HANDLED))
private fun decrypt(encryptedShell: EncryptedShell): String {
val decryptedShell = cryptoProvider.decrypt(encryptedShell)
return try {
decryptedShell.asString()
} finally {
decryptedShell.scramble()
}
}
}
private fun nestSlotText(nestSlotIndex: Int) = if (nestSlotIndex in 1..9) "Nest at Slot $nestSlotIndex" else "Default Nest"