The Gradle plugin provided for parsing configured files containing the DSL in order to construct a model of the FSM for visual representation. This model includes the content of the lambdas used in guards and actions.

Getting Started

Plugin Id: io.jumpco.open.kfsm.viz-plugin Version: 1.5.2.4

Gradle Groovy DSL

plugins {
    id 'io.jumpco.open.kfsm.viz-plugin' version '1.5.2.4'
}

Gradle Kotlin DSL

plugins {
    id("io.jumpco.open.kfsm.viz-plugin") version "1.5.2.4"
}

Configuration

Gradle Groovy DSL

kfsmViz {
  fsm('PacketReaderFSM') {
    input = file('src/main/kotlin/PacketReader.kt') // (1)
    isGeneratePlantUml = true // (2)
    isGenerateAsciidoc = true // (3)
    output = 'packet-reader' // (4)
    outputFolder = file('generated') // (5)
    plantUmlName = 'packet-reader-statediagram.plantuml' // (6)
    asciidocName = 'packet-reader-state-table.adoc'      // (7)
  }
}

Gradle Kotlin DSL

import io.jumpco.open.kfsm.gradle.VizPluginExtension
configure<VizPluginExtension> {
  fsm("PacketReaderFSM") {
    input = file("src/main/kotlin/PacketReader.kt") // (1)
    isGeneratePlantUml = true // (2)
    isGenerateAsciidoc = true // (3)
    output = "packet-reader" // (4)
    outputFolder = file("generated") // (5)
    plantUmlName = "packet-reader-statediagram.plantuml" // (6)
    asciidocName = "packet-reader-state-table.adoc"      // (7)
  }
}
  1. input: File: Required, relative path/name of relevant source file

  2. isGeneratePlantUml: Boolean: Required default is false

  3. isGenerateAsciidoc: Boolean: Required default is false

  4. output: String: Optional filename base. The default is the classname

  5. outputFolder: File: Optional directory for output file. Default is $buildDir/generated

  6. plantUmlName: String: Optional filename for plantuml output. Default is $output.plantuml

  7. asciidocName: String: Optional name of Asciidoc output file. Default is $output.adoc

Example with multiple state machines.

kfsmViz {
    fsm('TurnstileFSM') {
        input = file('resources/Turnstile.kt')
        output = 'turnstile'
        outputFolder = file('generated')
        isGeneratePlantUml = true
        isGenerateAsciidoc = true
    }
    fsm('PacketReaderFSM') {
        input = file('resources/PacketReader.kt')
        output = 'packet-reader'
        outputFolder = file('generated')
        isGeneratePlantUml = true
        isGenerateAsciidoc = true
    }
}

Expected output

Turnstile State Table

Start Event[Guard] Target Action

LOCKED

COIN

UNLOCKED

{
unlock()
}

UNLOCKED

COIN

UNLOCKED

{
returnCoin()
}

UNLOCKED

PASS

LOCKED

{
lock()
}

Turnstile State Diagram

simple turnstile

PacketReader State Table

Start Event[Guard] Target Action

[*]

CTRL [{it == CharacterConstants.SOH}]

RCVPCKT

RCVPCKT

CTRL [{it == CharacterConstants.STX}]

RCVDATA

{
addField()
}

RCVPCKT

BYTE

RCVCHK

{
addChecksum(it)
}

RCVDATA

BYTE

RCVDATA

{
addByte(it)
}

RCVDATA

CTRL [{it == CharacterConstants.ETX}]

RCVPCKT

{
endField()
}

RCVDATA

ESC

RCVESC

RCVESC

ESC

RCVDATA

{
addByte(CharacterConstants.ESC)
}

RCVESC

CTRL

RCVDATA

{
addByte(it)
}

RCVCHK

BYTE

RCVCHK

{
addChecksum(it)
}

RCVCHK

ESC

RCVCHKESC

RCVCHK

CTRL [{it == CharacterConstants.EOT}]

CHKSUM

{
checksum()
}

CHKSUM

<<automatic>> [{!checksumValid}]

[*]

{
sendNACK()
}

CHKSUM

<<automatic>> [{checksumValid}]

[*]

{
sendACK()
}

RCVCHKESC

ESC

RCVCHK

{
addChecksum(CharacterConstants.ESC)
}

RCVCHKESC

CTRL

RCVCHK

{byte->
require(byte != null)
addChecksum(byte)
}

PacketReader State Diagram

packet reader

Resources