Skip to content

Instantly share code, notes, and snippets.

@seb-martin
Created November 2, 2020 15:35
Show Gist options
  • Save seb-martin/46b8160b241653518c61198d456ba7f5 to your computer and use it in GitHub Desktop.
Save seb-martin/46b8160b241653518c61198d456ba7f5 to your computer and use it in GitHub Desktop.
import java.lang.IllegalArgumentException
import java.lang.IllegalStateException
import java.security.PrivateKey
import java.util.*
enum class Severity: Comparable<Severity> {
LOW, MEDIUM, HIGH
}
data class Overshoot(val severity: Severity)
interface WorkflowCommand
interface WorkflowStatus
enum class MediumSeverityWorkflowCommand: WorkflowCommand {
EXPLAIN, VALID, REJECT_EXPLANATION, REVERT_EXPLANATION, REVERT_VALIDATION,
}
enum class MediumSeverityStatus: WorkflowStatus {
WAITING_EXPLANATION, WAITING_VALIDATION, VALIDATED
}
enum class HighSeverityWorkflowCommand: WorkflowCommand {
EXPLAIN,
VALID_LOD1, REJECT_EXPLANATION, REVERT_EXPLANATION,
VALID_LOD2, REJECT_VALIDATION_LOD1, REVERT_VALIDATION_LOD1,
REVERT_VALIDATION_LOD2,
}
enum class HighSeverityStatus: WorkflowStatus {
WAITING_EXPLANATION, WAITING_LOD1_VALIDATION, WAITING_LOD2_VALIDATION, VALIDATED
}
data class Transition(val status: WorkflowStatus, val previousStatus: WorkflowStatus)
abstract class Workflow {
abstract val status: WorkflowStatus
abstract fun accept(c: WorkflowCommand): Boolean
abstract fun apply(c: WorkflowCommand): Transition
}
class MediumSeverityWorkflow private constructor(private var state: State = WaitingExplanationState()) : Workflow() {
companion object {
operator fun invoke(status: MediumSeverityStatus = MediumSeverityStatus.WAITING_EXPLANATION): MediumSeverityWorkflow {
return when (status) {
MediumSeverityStatus.WAITING_EXPLANATION -> MediumSeverityWorkflow()
MediumSeverityStatus.WAITING_VALIDATION -> MediumSeverityWorkflow(WaitingValidationState())
MediumSeverityStatus.VALIDATED -> MediumSeverityWorkflow(ValidatedState())
}
}
}
override val status: WorkflowStatus
get() = state.status
override fun accept(c: WorkflowCommand): Boolean {
return c is MediumSeverityWorkflowCommand && state.accept(c)
}
override fun apply(c: WorkflowCommand) = if (c is MediumSeverityWorkflowCommand) {
val previousStatus = this.state.status
this.state = this.state.apply(c)
Transition(state.status, previousStatus)
} else {
throw IllegalArgumentException("Illegal Command type: ${c.javaClass.kotlin}")
}
private interface State {
val status: MediumSeverityStatus
fun accept(c: MediumSeverityWorkflowCommand): Boolean
fun apply(c: MediumSeverityWorkflowCommand): State
}
private class WaitingExplanationState : State {
override val status: MediumSeverityStatus
get() = MediumSeverityStatus.WAITING_EXPLANATION
override fun accept(c: MediumSeverityWorkflowCommand): Boolean = when(c) {
MediumSeverityWorkflowCommand.EXPLAIN -> true
else -> false
}
override fun apply(c: MediumSeverityWorkflowCommand): State = when (c) {
MediumSeverityWorkflowCommand.EXPLAIN -> WaitingValidationState()
else -> throw IllegalStateException()
}
}
private class WaitingValidationState : State {
override val status: MediumSeverityStatus
get() = MediumSeverityStatus.WAITING_VALIDATION
override fun accept(c: MediumSeverityWorkflowCommand): Boolean = when(c) {
MediumSeverityWorkflowCommand.REVERT_EXPLANATION -> true
MediumSeverityWorkflowCommand.VALID -> true
MediumSeverityWorkflowCommand.REJECT_EXPLANATION -> true
else -> false
}
override fun apply(c: MediumSeverityWorkflowCommand): State = when (c) {
MediumSeverityWorkflowCommand.REVERT_EXPLANATION -> WaitingExplanationState()
MediumSeverityWorkflowCommand.VALID -> ValidatedState()
MediumSeverityWorkflowCommand.REJECT_EXPLANATION -> WaitingExplanationState()
else -> throw IllegalStateException()
}
}
private class ValidatedState : State {
override val status: MediumSeverityStatus
get() = MediumSeverityStatus.VALIDATED
override fun accept(c: MediumSeverityWorkflowCommand): Boolean = when(c) {
MediumSeverityWorkflowCommand.REVERT_VALIDATION -> true
else -> false
}
override fun apply(c: MediumSeverityWorkflowCommand): State = when (c) {
MediumSeverityWorkflowCommand.REVERT_VALIDATION -> WaitingValidationState()
else -> throw IllegalStateException()
}
}
}
class HighSeverityWorkflow() : Workflow() {
override val status: HighSeverityStatus
get() = HighSeverityStatus.WAITING_EXPLANATION
override fun accept(c: WorkflowCommand): Boolean {
TODO("Not yet implemented")
}
override fun apply(c: WorkflowCommand) : Transition {
TODO("Not yet implemented")
}
}
object WorkflowFactory {
fun createWorkflow(overshoot: Overshoot): Optional<Workflow> {
return when (overshoot.severity) {
Severity.LOW -> Optional.empty()
Severity.MEDIUM -> Optional.of(MediumSeverityWorkflow())
Severity.HIGH -> Optional.of(HighSeverityWorkflow())
}
}
}
fun main() {
lowSeverityWorkflow()
mediumSeverityWorkflow()
// TODO("highSeverityWorkflow()")
}
private fun mediumSeverityWorkflow() {
val overshoot = Overshoot(Severity.MEDIUM)
val optionalWorkflow = WorkflowFactory.createWorkflow(overshoot)
assert(optionalWorkflow.isPresent)
optionalWorkflow.ifPresent {
assert(it.status == MediumSeverityStatus.WAITING_EXPLANATION)
assert(!it.accept(HighSeverityWorkflowCommand.EXPLAIN))
assert(it.accept(MediumSeverityWorkflowCommand.EXPLAIN))
println(MediumSeverityWorkflowCommand.EXPLAIN)
var transition = it.apply(MediumSeverityWorkflowCommand.EXPLAIN)
println(transition)
assert(it.status == MediumSeverityStatus.WAITING_VALIDATION)
println(MediumSeverityWorkflowCommand.REVERT_EXPLANATION)
transition = it.apply(MediumSeverityWorkflowCommand.REVERT_EXPLANATION)
println(transition)
assert(it.status == MediumSeverityStatus.WAITING_EXPLANATION)
println(MediumSeverityWorkflowCommand.EXPLAIN)
transition = it.apply(MediumSeverityWorkflowCommand.EXPLAIN)
println(transition)
assert(it.status == MediumSeverityStatus.WAITING_VALIDATION)
println(MediumSeverityWorkflowCommand.REJECT_EXPLANATION)
transition = it.apply(MediumSeverityWorkflowCommand.REJECT_EXPLANATION)
println(transition)
assert(it.status == MediumSeverityStatus.WAITING_EXPLANATION)
println(MediumSeverityWorkflowCommand.EXPLAIN)
transition = it.apply(MediumSeverityWorkflowCommand.EXPLAIN)
println(transition)
assert(it.status == MediumSeverityStatus.WAITING_VALIDATION)
println(MediumSeverityWorkflowCommand.VALID)
transition = it.apply(MediumSeverityWorkflowCommand.VALID)
println(transition)
assert(it.status == MediumSeverityStatus.VALIDATED)
println(MediumSeverityWorkflowCommand.REVERT_VALIDATION)
transition = it.apply(MediumSeverityWorkflowCommand.REVERT_VALIDATION)
println(transition)
assert(it.status == MediumSeverityStatus.WAITING_VALIDATION)
}
}
private fun lowSeverityWorkflow() {
// A low severity overshoot do not have workflow
val lowSeverityOvershoot = Overshoot(Severity.LOW)
val lowSeverityOvershootWorkflow = WorkflowFactory.createWorkflow(lowSeverityOvershoot)
assert(!lowSeverityOvershootWorkflow.isPresent)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment