Skip to content

Commit

Permalink
Added state machine to the callback function
Browse files Browse the repository at this point in the history
- Improved test coverage
- Updated jacoco
  • Loading branch information
ToxicBakery committed May 31, 2019
1 parent bebe7e6 commit ac0add3
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 13 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ buildscript {
ext.supportLibrary_version = '28.0.0'
ext.rxjava_version = '2.1.9'
ext.contraint_layout_version = '1.1.3'
ext.jacoco_version = '0.8.3'
ext.jacoco_version = '0.8.4'

repositories {
google()
Expand Down Expand Up @@ -35,7 +35,7 @@ subprojects {
String buildNumber = System.getenv('CIRCLE_BUILD_NUM') ?: "0"

group 'com.ToxicBakery.kfinstatemachine'
version "4.0.$buildNumber" + (isTag ? "" : "-SNAPSHOT")
version "4.1.$buildNumber" + (isTag ? "" : "-SNAPSHOT")

repositories {
mavenCentral()
Expand Down
13 changes: 10 additions & 3 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,19 @@ kotlin {
task jacocoTestReportJvm(type: JacocoReport) {
classDirectories = files(
"$buildDir/classes/kotlin/common/main",
"$buildDir/classes/kotlin/jvm/main")
"$buildDir/classes/kotlin/jvm/main",
"$buildDir/classes/kotlin/jvmRx/main"
)
sourceDirectories = files(
"src/commonMain/kotlin",
"src/jvmMain/kotlin")
"src/jvmMain/kotlin",
"src/jvmRxMain/kotlin"
)
//noinspection ChangeToOperator
executionData = files("$buildDir/jacoco/jvmTest.exec")
executionData = files(
"$buildDir/jacoco/jvmTest.exec",
"$buildDir/jacoco/jvmRxTest.exec"
)

reports {
xml.enabled = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,20 @@ package com.toxicbakery.kfinstatemachine

import kotlin.reflect.KClass

/**
* A basic state machine that is not thread safe.
*/
open class StateMachine<S, T : Any> : IStateMachine<S, T> {

private val transitionRules: Array<TransitionDef<S, out T>>
private val transitionCallbacks: MutableList<TransitionCallback<S, T>> = mutableListOf()

private val _transitionCallbacks: MutableList<TransitionCallback<S, T>> = mutableListOf()

/**
* An immutable list of the currently registered callbacks.
*/
val transitionCallbacks: List<TransitionCallback<S, T>>
get() = _transitionCallbacks

final override var state: S

Expand Down Expand Up @@ -35,9 +45,13 @@ open class StateMachine<S, T : Any> : IStateMachine<S, T> {
override fun transition(transition: T) {
val currentState = state
val edge = edge(transition)
transitionCallbacks.forEach { cb -> cb.enteringState(state, transition, edge.newState) }
transitionCallbacks.forEach { cb ->
cb.enteringState(this, state, transition, edge.newState)
}
state = edge.newState
transitionCallbacks.forEach { cb -> cb.enteredState(currentState, transition, edge.newState) }
transitionCallbacks.forEach { callback ->
callback.enteredState(this, currentState, transition, edge.newState)
}
}

@Suppress("UNCHECKED_CAST")
Expand All @@ -56,15 +70,15 @@ open class StateMachine<S, T : Any> : IStateMachine<S, T> {
* @param transitionCallback to be registered
*/
fun registerCallback(transitionCallback: TransitionCallback<S, T>) =
transitionCallbacks.add(transitionCallback)
_transitionCallbacks.add(transitionCallback)

/**
* Unregister a callback from state transition updates.
*
* @param transitionCallback to be unregistered
*/
fun unregisterCallback(transitionCallback: TransitionCallback<S, T>) =
transitionCallbacks.remove(transitionCallback)
_transitionCallbacks.remove(transitionCallback)

private fun edge(transition: Any): TransitionDef<S, *> = transitionRules
.filter { transitionRule ->
Expand Down Expand Up @@ -107,11 +121,13 @@ interface TransitionCallback<S, T : Any> {
/**
* After a state transition has been verified to be legal but has not yet been applied to the machine.
*
* @param stateMachine the machine notifying the state change
* @param currentState the current state of the machine
* @param transition the transition that initiated the state change
* @param targetState the resulting state of this transition
*/
fun enteringState(
stateMachine: StateMachine<S, T>,
currentState: S,
transition: T,
targetState: S
Expand All @@ -120,11 +136,13 @@ interface TransitionCallback<S, T : Any> {
/**
* After a state transition has been verified to be legal and also applied to a machine.
*
* @param stateMachine the machine notifying the state change
* @param previousState the previous state of the machine before the transition was applied
* @param transition the transition that initiated the state change
* @param currentState the resulting state of this transition
*/
fun enteredState(
stateMachine: StateMachine<S, T>,
previousState: S,
transition: T,
currentState: S
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ sealed class TransitionEvent<S, T : Any> {
* @param targetState the resulting state of this transition
*/
data class EnterTransition<S, T : Any>(
val stateMachine: StateMachine<S, T>,
val currentState: S,
val transition: T,
val targetState: S
Expand All @@ -37,6 +38,7 @@ sealed class TransitionEvent<S, T : Any> {
* @param currentState the resulting state of this transition
*/
data class ExitTransition<S, T : Any>(
val stateMachine: StateMachine<S, T>,
val previousState: S,
val transition: T,
val currentState: S
Expand All @@ -54,15 +56,17 @@ private class RxStateCallback<S, T : Any>(
) : TransitionCallback<S, T> {

override fun enteringState(
stateMachine: StateMachine<S, T>,
currentState: S,
transition: T,
targetState: S
) = emitter.onNext(EnterTransition(currentState, transition, targetState))
) = emitter.onNext(EnterTransition(stateMachine, currentState, transition, targetState))

override fun enteredState(
stateMachine: StateMachine<S, T>,
previousState: S,
transition: T,
currentState: S
) = emitter.onNext(ExitTransition(previousState, transition, currentState))
) = emitter.onNext(ExitTransition(stateMachine, previousState, transition, currentState))

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class RxStateMachineTest {

var currentState: Energy = stateMachine.state

stateMachine.stateObservable
val disposable = stateMachine.stateObservable
.filter { event -> event is ExitTransition }
.map { event -> event as ExitTransition<Energy, EnergyTransition> }
.map { event -> event.currentState }
Expand Down Expand Up @@ -62,7 +62,10 @@ class RxStateMachineTest {
setOf(Release::class),
stateMachine.transitionsTo(Kinetic))

// Cleanup
disposable.dispose()

assertEquals(0, stateMachine.transitionCallbacks.size)
}

}

0 comments on commit ac0add3

Please sign in to comment.