Created
November 2, 2020 15:35
-
-
Save seb-martin/46b8160b241653518c61198d456ba7f5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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