Developing a custom code generator by example of SCXML
This blog post explains how to develop a custom code generator for the open source framework YAKINDU Statechart Tools. As an example, we will generate Statechart XML (SCXML) from a simple stop watch state machine.
The stop watch use case is taken from the Apache Commons SCXML site. The stop watch model consists of 4 different states (ready, running, stopped and paused) and the state transitions are triggered by events that represent the stop watch buttons (watch.start, watch.stop, watch.split, watch.unsplit, watch.reset).
Note that this example is not a full fletched Statechart XML code generator; only the basic concepts of states, transitions and events are supported to showcase how to get started. We expect the following XML fragment to be generated from the model above:
<?xml version="1.0" encoding="UTF-8"?> <scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="ready"> <state id="ready"> <transition event="watch.start" target="running" /> </state> <state id="running"> <transition event="watch.split" target="paused" /> <transition event="watch.stop" target="stopped" /> </state> <state id="paused"> <transition event="watch.stop" target="stopped" /> <transition event="watch.unsplit" target="running" /> </state> <state id="stopped"> <transition event="watch.reset" target="ready" /> </state> </scxml>
SExec and SGraph meta models
Before starting with a code generator, we have to decide which of the two available meta models is most suitable for the use case. In model driven software development, a model always conforms to another model commonly referred to as a meta model. This meta model defines the building blocks a model can consist of. When developing a generator for YAKINDU SCT you can choose between two different meta models, SGraph and SExec. In broad terms, SGraph represents the structure of the modeled statemachine (States, Transitions, Events) while SExec contains sequences that encapsulates our execution semantics (for example Checks, Calls and Stateswitch).
The SGraph meta model is similar to the state machine meta model known from the UML. We have a top level element Statechart that contains a set of States and Transitions. Transitions may have events and a source and a target State. The following shows a very simplified version of SGraph.
In contrast, the SExec meta model defines an ExecutionFlow that contains a set of ExecutionStates. Every ExecutionState has an entry and an exit sequence of several Steps. Each Step can be of a different type, for example a StateSwitch or a Check.
If you want to generate code for a runtime environment that interprets a statechart structure (for example SCXML or Spring Statemachine) you should pick SGraph meta model. If you want to generate a code-only approach for another programming language, and you want to ensure that it behaves exactly in the way all the other code generators behave, you should pick the SExec meta model.
The example Statechart XML generator
Creating custom code generators is really easy. It is a first-level concept in YAKINDU Statechart Tools. You can develop them directly within your project workspace which has the nice benefit that adoptions to the model or the generator templates are executed instantly, hence you don't have to bother with long code-compile-test cycles. More information about how to setup a new code generator project is out of the scope of this blog post and can be found in the user guide.
When choosing the language for developing a new generator, you should consider using Xtend instead of Java. The syntax is familiar for every Java developer, but it adds some nice features like template expressions and dispatch methods that are really useful for developing code generators.
The example Statechart XML generator implemented with Xtend could look like this:
The SCXMLGenerator class extends AbstractWorkspaceGenerator to inherit some utility functions and implements the ISGraphGenerator interface (line 17). This interface defines which meta model will be used for the code generator. If you want to implement a code generator based on the ExecutionFlow meta model you would implement IExecutionFlowGenerator interface instead.
The generate function in line 23 uses Xtends template string to generate the SCXML header. Most of the text ist static except for the value of the initial attribute - this is calculated in the initialState function (line 30). Below the SCXML header, the generate function for the head region (parallel regions are not implemented) is called (line 26). This function (line 34) simply iterates over all states in this region and calls the generate function for states (line 40). Other vertex types, for example Histories, Synchronizations or Final States are filtered out. Last, the generate function for states creates a new XML element and iterates over all outgoing transitions to generate the nested transition element.
You can download the example generator project from our new examples repository. However, this is just a first step towards a full fletched SCXML code generator. Feel free to take this example as a starting point but don't forget to contribute your extensions to our repository! If you have any questions or need further support on implementing custom code generators feel free to contact us.