Code Generation and Execution Framework for UML 2.0 Classes

Code Generation and Execution Framework
for UML 2.0 Classes and State Machines
Romuald Pilitowski, Anna Derezińska
Institute of Computer Science, Warsaw University of Technology
15/19 Nowowiejska Street
Warsaw, 00-665 Poland
Abstract – The paper presents Framework for eXecutable UML
(FXU). FXU transforms UML models into programming code and
supports execution of the resulting application according to the
behavioral model. The code generation and execution is based on
UML classes and their state machines. The FXU framework takes
into account all concepts of state machines defined by the UML
2.0 specification. Ambiguities of UML state machine
interpretation had to been resolved within the framework in
order to obtain an executable application. During the runtime
execution separate state machines and orthogonal regions are run
as parallel threads. All kinds of events, states, pseudostates and
activities are processed, as well. The framework was implemented
and tested for C# code. The tool supports model-driven
development of high quality applications.
I. INTRODUCTION
Unified Modeling Language (UML) is a widely accepted,
graphical language for specification, analysis and design of
object-oriented computer systems [1]. Emergence of UML has
triggered development of many tools and methodologies that
improve quality of computer systems [2-9]. One of such
methodologies is Executable UML (xUML) [10] that is
intended to enable UML models to be translated into
executable code. As such, an Executable UML model can be
treated as Platform Independent Model (PIM) – the concept
defined within the Model Driven Architecture (MDA). MDA
is a recent initiative of Object Management Group consortium
(OMG) which contributed to the development of the UML
standard [2]. MDA is a model-centric approach to the software
engineering based on models as major artifacts of the
development process. However, none of the MDA tools
supports complete and precise transformation of UML 2.0
state machines into executable C# code.
Our solution, called Framework for eXecutable UML
(FXU) developed at the Warsaw University of Technology is
an example of xUML tool. It is a code generator which enables
transformation of UML 2.0 class diagrams and state machines
into code in C# programming language, which can be further
compiled and executed. A distinguishing feature of FXU is its
ability to handle every single element of state machines as
defined by the OMG standard – the UML 2.0 specification [1].
FXU consists of two components – FXU Generator and
FXU Runtime Library. The FXU Generator transforms a UML
2.0 model into the corresponding code in the programming
language. It takes into account information from class
diagrams and state machines. The FXU Runtime Library is a
library that implements entire logic of state machines as
described by the UML 2.0 specification, including states,
events, transitions etc. Both generated code and the FXU
Runtime Library are required in order to enable execution of
state machines.
The paper presents core algorithms that were implemented
by the FXU Runtime Library. It supports execution of
concurrent state machines which can specify behavior of many
different objects. Regions of orthogonal states are executed
concurrently as well. Transitions across vertices are triggered
by events. The selection of transitions to be fired is based on
their priorities. Queues of events are handled for each active
state machine.
During development of FXU we faced problems of
inconsistency of UML 2.0 specification concerning state
machines. Some of the issues are semantic variation points.
Semantic variation points are aspects that were intentionally
not determined in order to leave its interpretation to a user.
The order in which events are removed from the event pool is
an example of the semantic variation point. However, there are
also aspects such as the order of execution of multiple
transitions, that were clearly overlooked in the specification.
There are about ten inconsistency issues that cannot be
resolved on the basis of the specification. All of them had to
be identified and interpreted before the implementation of
FXU. A detailed description exceeds however the scope of this
paper [11].
Section II describes principles of code generation and the
architecture of the FXU Generator. The FXU Runtime Library
and its essential algorithms are presented in Section III.
Related work is discussed in Section IV and final remarks end
the paper.
The original publication is available at http://www.springerlink.com/content/m2578mu420796236/
II. CODE GENERATION FROM UML MODELS
Code generators from UML models transform an abstract
model of a software system into its implementation. Output of
the most simple code generators from UML models [4,5,7] is
only a stub of a system, e.g. only class declarations that have
to be implemented. Approach of MDA is different. It assumes
generation of the most components of the target system
without much human intervention afterwards. FXU enables
generation of fully functional applications as long as their
structure and behavior can be represented using UML 2.0 class
diagrams and state machines.
The distinguishing feature of FXU is the ability to generate
and execute every single aspect of state machines described in
the UML 2.0 specification. They are all listed in Tab. 1.
TABLE 1
ELEMENTS OF STATE MACHINES SUPPORTED BY FXU
States: simple states, composite (including orthogonal) states, entry-, do-,
exit activities, submachine states.
Pseudostates: initial pseudostate, deep and shallow history, join, fork,
junction, choice, entry and exit point, terminate.
Transitions: external, local, internal transitions, guards, actions, priorities
of transitions.
Events: call events, time events, completion events, change events,
signals, deferred evens, priorities of dispatching.
A. Code generation from class diagrams.
Generation from class diagrams to an object-oriented
language is straight-forward. The most of the concepts from
class diagrams have their counterparts in object-oriented
languages. The FXU Generator and most other similar
generators transform classes, their operations and attributes as
well as interfaces into corresponding instructions in
programming languages. Some generators including the FXU
Generator support also generation of associations. The FXU
Generator provides also with a template of generated code that
can be edited in order to adjust outcome of generation to
individual requirements.
purpose languages. For example, there is no counterpart of a
transition or a state in the most general-purpose languages.
Therefore every single concept defined in the UML 2.0
specification as a state, event, transition etc. was implemented
and wrapped by a class of the FXU Runtime Library. The
generated code consists mainly of instances of the FXU
Library classes.
C. Code template
Figure 1 illustrates how FXU merges a UML 2.0 class and
its state machines into one file with source code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$visibility class $class_name {
$visibility [static] [readonly] $type $attribute_name;
StateMachine sm = new
StateMachine($state_machine_name);
$visibility [static] $return_type $method_name
($type $parameter_name1, $type $parameter_name2) {
$method_implementation
}
public void InitFxu(){
Create regions
Create states
Add the states to the nesting regions
Add activities to the states
Add events deferred by the states
Create pseudostate
Add the pseudostates to the regions
Create transitions
Add triggers of the transitions
Add guards to the transitions
Add actions to the transitions
}
public void StartFxu(){
State::Enter ( sm );
}
}
Fig. 1. Template of generated source files.
B. Code generation from state machines.
Major goal of our solution is generation and execution of
state machines. However, classes play an important role in
both generation and execution of state machines because they
create context for them. Every class can possess one or more
state machines that describe behavior of its instances.
Elements of the UML 2.0 model which are accessible within
context of the class are also accessible within its state
machines. Therefore, generation of state machines involves
generation of corresponding classes.
Code generation from state machines is by far more difficult
to accomplish than generation from class diagrams. The main
reason for this is the lack of direct and precise mapping
between concepts borrowed from state diagrams and general-
Every class from the input model is generated as a separate
file. Each class begins with declaration of its attributes (line 3).
Keywords static and readonly are parameters of attributes and
refer to UML properties of the same name. State machines of
the class are treated as attributes of type StateMachine (rows
5-6). StateMachine and other types as State, Transition,
InitialPseudostate are classes defined by the FXU Library.
Next, operations are declared (lines 8-9). If an operation is
not abstract, its body is generated as well. Provided the input
model contains an implementation, it is also included in the
generated code. In case an operation triggers a call event,
instructions broadcasting the appropriate event are added to
the implementation of the operation.
The original publication is available at http://www.springerlink.com/content/m2578mu420796236/
If the class contains state machines, two methods InitFxu
and StartFxu are also generated. InitFxu builds structures of
state machines of the class. First, regions – sets of vertices that
contain at most one active vertex, are created (line 13). Next,
vertices, i.e. states and pseudostates are defined and added to
the regions (rows 14-19). Finally, transitions across vertices
are formed (20-23). The second method, StartFxu starts
execution of all state machines owned by the class.
D. FXU Generator
The FXU Generator imports an XML Metadata Interchange
(XMI) file with a UML 2.0 model. XMI is an OMG standard
that can be used to exchange theoretically any model that can
be expressed in Meta-Object Facility (MOF). Most present
CASE tools support export of UML models to an XMI file,
although several incompatible versions of XMI exist. We use
an XMI variant supported by Eclipse sub-project called UML2
[12]. After import of the model, the FXU Generator applies
transformation rules to class and state diagrams which results
in generation of the corresponding source code. The source
code may be obviously further developed by a user, but more
importantly it can be compiled and linked against the FXU
Runtime Library. The obtained executable binary file fully
emulates the behavior of the input state machines.
Figure 2 depicts major components of the FXU Generator.
It depends on two external libraries – UML2 and Jxp. UML2
is an open-source library for serialization and deserialization
of UML 2.0 models stored in XMI format. UML2 library is
utilized among others by Rational Software Modeler (version
6.0) and its more advanced edition Rational Software
Architect [7]. Therefore, the FXU Generator integrates well
with these CASE tools. Template processor Jxp is another
external library used by the FXU Generator. We provide with
Jxp templates for transformation of both classes and interfaces,
which can be edited and customized by a user. The generator
applies transformation rules to classes as well as state
machines and uses Jxp for rendering the output files. Jxp
combines the templates with the input model and generates the
source code.
III. FXU RUNTIME LIBRARY
A. Overview of FXU Runtime Library
The FXU Library implements the logic behind UML 2.0
state diagrams. A source code obtained as an output of the
FXU Generator or written by hand is executed within the
environment of the FXU Library. Figure 3 presents how a
source code rendered by the FXU Generator and the FXU
Library interact with each other.
Source code generated
by FXU Generator
Source code written
manually
FXU Runtime Library
CPU
Fig. 3. Execution of state machines using FXU.
The FXU Library emulates behavior of UML 2.0 state
diagrams. Because this behavior is universal for all UML 2.0
state machines, it was implemented as a component which is
reused every time the state machines are being executed. The
library consists of over forty classes. Each of them realizes a
single concept defined by the specification such as a state, a
transition, a fork pseudostate etc. Figure 4 depicts the
essentials of state diagrams implemented in the FXU Runtime
Library.
Fig. 4. FXU Runtime Library. Basic elements.
Fig. 2. Architecture of the FXU Generator.
Execution of separate state machines and orthogonal regions
is implemented through parallel threads. A state machine can
react on different events defined in the UML model. The FXU
Library realizes event processing (Fig. 5).
Each state machine has exactly one event pool which
contains received but still not processed events. The order of
events in the event pool is a semantic variation point. FXU
treats events on the First-In First-Out basis. However,
completion events have always the highest priority. It is the
only exception enforced by the specification. An event can
The original publication is available at http://www.springerlink.com/content/m2578mu420796236/
trigger any number of transitions. However, it has to be sent
first. Events can be either broadcasted to all the state machines
through EventBroadcaster singleton or can be sent directly to
the selected state machines.
Fig. 5. FXU Runtime Library. Event processing.
B. Algorithms
State diagrams are by nature concurrent. Not only because
more than one state machine may be running at the same time.
Also a single state can contain more than one parallel region.
Such a state is called orthogonal and also requires concurrent
execution of some activities, e.g. traversing, entering substates
or execution of do activities. Event processing is another task
which works continuously for each active state machine and
should be run simultaneously to the execution of a state
machine. Every state machine disposes over own event pool
which implements producers-consumer algorithm. Every
element of a state machine can produce, i.e. send events but
only the appropriate state machine can process them. For these
reasons the FXU Runtime Library takes advantage of
multithreading to a large extent.
We present core algorithms implemented by the FXU
Runtime Library: the algorithm of execution of a state machine
(Fig. 6), of entrance and of exit from a state (Fig. 7 and 8).
Execution of a state machine starts with its static
validation (Fig. 6 line 3-4). Static validation verifies
correctness of the structure of the state diagram, e.g. ensures
that every initial pseudostate has exactly one outgoing
transition. If the state machine is invalid, it cannot be
launched.
Then, the state machine is entered (row 5). Detailed
algorithm of entry to a state is presented in Figure 7.
Event processing and traversing is executed in the loop
(lines 6-22). Its execution can be broken if either a final state
of the state machine was entered or it was terminated. The
state machine terminates when either a terminate pseudostate
is entered or a critical malfunction in its behavior was
detected, e.g. there are no enabled transitions outgoing from an
active choice pseudostate.
In the next step, transitions to be fired are computed. First,
the event with the highest priority is removed from the event
pool (10-12). Then, currently enabled transitions are
computed. An enabled transition is such a transition that is
triggered by the event, whose source state is active and whose
guard condition evaluates to true. The transitions to be fired
are selected from the enabled ones. But because some
transitions cannot be traversed at the same time, not every
enabled transition will be fired. Priorities of transitions decide
which of enabled transitions can be launched. However, the
definition of transition priority provided by the UML 2.0
specification is not sufficient to resolve all conflicts.
Therefore, we had to extend the definition of transitions
priority. Selection of non conflicting transitions on the basis of
our definition is possible in any state configuration. Its detailed
description exceeds the scope of this paper [11].
Next, the deferred events are handled. If a deferred event
fires no transition, it returns to the event pool (rows 15-19).
A not-deferred event would be ignored and lost in such cases.
Finally, the selected non-conflicting transitions are fired in
concurrent threads. In consequence no single transition is
favored. After all transitions had been traversed, the next event
can be removed from the event pool and the entire procedure
repeats.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
PROCEDURE
StateMachine::Enter(StateMachine: sm ) {
IF ( static validation of sm fails) THEN
RETURN
State::Enter(sm)
WHILE ( TRUE ) DO {
IF ( final state of sm was entered OR
sm was terminated ) THEN
RETURN
Let e be the event with the highest priority among all
events in the event pool
Remove event e from the event pool
Let M be a set of enabled transitions triggered by e which
were selected to be fired
IF ( set M is empty AND
exist active state which defers event e ) {
Add e to the event pool
CONTINUE
}
FOREACH transition t ∈ M DO
Traverse transition t in a concurrent thread
}
}
Fig. 6. Algorithm of execution of a state machine.
Figure 7 presents the algorithm of entry to a state. It
applies also to state machines which are treated as the special,
outermost states.
Before entrance to a state we assure that it is still inactive.
Instructions in lines from 2nd to 4th are invoked as atomic,
thread-safe operations.
The original publication is available at http://www.springerlink.com/content/m2578mu420796236/
Next, a new thread, called after-thread is created and fired
asynchronously for each time event which triggers a transition
outgoing from the state. The after-thread sleeps for the time
interval defined by the corresponding time event, wakes up
and adds it to the event pool (lines 5-8).
Then, all nesting states of the state s are entered recursively
(line 10). It reflects the rule that nesting states are entered
before the nested ones. Afterwards shallow and deep history of
the nesting states are being updated (row 11 and 13).
After execution of entry activity (line 14), do activity of the
sate is being executed in a separate, parallel thread, called dothread (row 15). Completion-thread is another concurrent
thread that sends its completion event for the state once the
execution of do activity finished (line 16).
Next, the inactive regions nested by the state are activated.
Activation of a region means entering an indicated vertex
nested by this region or its initial pseudostate.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
PROCEDURE State::Enter (State: s){
IF (state s is inactive) THEN
Mark state s as active
ELSE RETURN
FOREACH transition t outgoing from s DO
FOREACH event e triggering t DO
IF( e is a time event) THEN
Run after-thread
IF(exists state ns directly nesting s ) THEN {
State::Enter( ns )
Update shallow history of ns
}
Update deep history of all states nesting s
Execute entry activity of s
Run do-thread
Run completion-thread
FOREACH region r nested by s DO
IF ( r is inactive ) THEN
Run region-activation- thread
}
1
2
3
4
5
6
7
8
9
10
11
12
13
PROCEDURE Exit (State: s){
IF (state s is active) THEN
Mark state s as inactive
ELSE RETURN
Stop after-thread
Stop completion-thread
Stop do-thread
FOREACH region r nested by s DO {
Let ns be the only active state nested by r
State::Exit ( ns )
}
Execute exit activity of s
}
Fig. 8. Algorithm of exit from a state.
C. Example of state machine execution
The following example illustrates the process of state
machine execution. The input model consists of a single class
TvSet (Fig. 9) and a state diagram specifying its behavior
(Fig. 10). The state machine has two states, a simple state Off
and a complex state On with two orthogonal regions.
Fig. 9. TvSet class.
Fig. 7. Algorithm of entry to a state.
Exiting a state (Fig. 8) is a process opposite to the entrance.
First, we assure, that the state is still inactive (lines 2-4). If the
state is inactive, it cannot be exited once again. Instructions in
lines from 2nd to 4th are invoked as atomic operations and can
be therefore safely executed by concurrent threads.
Then, after-, completion- and do-thread are stopped
(rows 5-7). According to the UML 2.0 specification, do
activity of a state may be terminated, if the exit had been
requested.
After that, all the nested active states are being exited, which
implements principle, that exit from nesting states follows exit
from nested ones (lines 8-10).
Finally, the exit activity of the state is executed (line 12).
Fig. 10. State machine of TvSet class.
Provided that the above model is used as an input of the
FXU Generator, a single file containing definition of the TvSet
class and the implementation of its state machine would be the
output of the generation. After compilation and linking against
the FXU Runtime Library the state machine can be executed.
The execution of the state machine starts with entering its
only initial pseudostate. Then, the state Off is entered.
According to the algorithm (Fig. 7), entry-activity and then
asynchronously do-activity are executed. After the do-activity
The original publication is available at http://www.springerlink.com/content/m2578mu420796236/
finishes, a completion event for the state Off is sent. However,
a call event PowerButton is the only event that triggers
transitions outgoing from the state Off and the completion
event is lost. If the PowerButton method is invoked now, the
corresponding PowerButton call event is sent and transition to
the fork pseudostate proceeds. Transitions from the fork
pseudostate result in the execution of two concurrent threads
that activate states PlayingSound and DispalyingMovie as well
as their nesting state On. So long the state On is active,
a transition back to the state Off can be fired, if the
PowerButton event is raised again. Otherwise, after doactivities of states PlayingSound and DispalyingMovie finish,
the corresponding completion events are sent. Consequently,
transitions to the join pseudostate are entered and finally the
final state is entered. As a result, the execution of the state
machine is finished.
IV. RELATED WORK
FXU is one of the existing solutions that enable execution of
state machines. Crane and Dingel have conducted survey of
various different approaches to the problem of state machines
modeling [3]. According to their study and our own research
most of the code generators support only fundamental aspects
of state machines described by the UML 2.0 specification.
More advanced elements such as deferring events are generally
not supported. A notable exception is Rhapsody of Telelogic
AB (formerly I-Logix), which generates code from UML 2.0
state diagrams for C, C++, Ada and Java [6]. The unique
feature of FXU is however its ability to transform all details of
UML 2.0 state machines into C# code.
Two general approaches to code generation from state
machines exist. The first one assumes no existence of any
library or virtual machine which implement semantic of state
machines [8, 13]. Therefore, large number of code must be
generated even for simple state diagrams. The approach we
prefer involves using a library (in our case the FXU Runtime
Library) which hides all the logic of state diagrams [6, 9].
Therefore there is less code to generate. Consequently,
generated sources are easier to understand and to edit. Such an
approach enables also relatively easy reverse-engineering of
state machines.
over fifty UML models, including complex state machines and
models with non-trivial class diagrams published on the
Internet.
The purpose of FXU is to help developing robust
applications in C#. The major advantage of FXU for
a programmer is the efficient development of multithreaded,
well-documented and maintainable applications.
FXU is the proof of the concept that complete and precise
transformation of UML 2.0 state machines into executable
code is possible. However, developing computer systems with
FXU requires in-depth knowledge of state machines and is
limited to specific class of problems, i.e. such problems that
can be modeled with state diagrams.
Behavioral verification of UML models, especially state
machines, can be provided using model checking techniques
[14]. We are able to check whether UML state machines
satisfy specified dynamic features, in the most cases analyzing
the models translated into the appropriate notation of
verification tools (e.g. SPIN[15]). Later, FXU can convert the
same, verified UML models into an application, retaining the
desired features after model to code transformation.
State machines are expected to attract more attention with
increase of popularity of MDA tools which require more
precise specification of computer systems.
REFERENCES
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[10]
[11]
[12]
V. FINAL REMARKS
The paper presented Framework for eXecutable UML
(FXU). The framework was implemented in Java 1.5 (FXU
Generator) and in C# 2.0 (FXU Runtime Library). The
presented solution realizes all basic features of the class
diagrams and the complete description of the UML 2.0 state
machines. FXU was used to generate and execute C# code of
[13]
[14]
[15]
UML 2.0 specification, http://www.uml.org/#UML2.0
The Object Management Group (OMG), http://www.omg.org/
M. Crane, J. Dingel, On the Semantics of UML State Machines:
Categorization and Comparison., Tech. Rep. 2005-501, School of
Computing, Queens University of Kingston, Ontario, Canada, 2005.
Poseidon for UML, http://www.gentleware.com/
MagicDraw UML, http://www.magicdraw.com/
Rhapsody, http://www.ilogix.com/
T. Quatrani, J. Palistrant, Visual Modeling with IBM Rational
Software Architect and UML, 1st ed, IBM Press, May 2006.
SmartState, http://www.smartstatestudio.com
A. Knapp, S. Merz, C. Rauh. „Model Checking Timed UML State
Machines and Collaborations”, in Proc. 7th Int. Symp. Formal
Techniques in Real-Time and Fault Tolerant Syst., 2002, pp.395-414.
S. J. Mellor, M. J. Balcer, Executable UML a Fundation for ModelDriven Architecture, Addison-Wesley, 2002.
R. Pilitowski, Generation of C# code from UML 2.0 class and state
machine diagrams (in Polish), Master thesis, Inst. of Computer
Science, Warsaw University of Technology, Poland, 2006.
F. Budinsky, D. Steinberg, E. Merks, R. Ellersick,T. Grose, Eclipse
Modeling Framework, 1st ed, Addison-Wesley, Aug. 2003.
Iftikhar Azim Niaz, Jiro Tanaka, "Mapping UML Statecharts into Java
code", in Proc. of the IASTED Int. Conf. Software Engineering, Feb.
2004, pp. 111-116.
M. Gallardo, P. Merino, E. Pimentelis, "Debugging UML Designs with
Model Checking", in Journal of Object Technology, vol. 1., no. 2, pp.
101-117, July-August 2002.
G. J. Holzmann, The SPIN Model Checker: Primer and Reference
Manual, Addison Wesley, 2003.
The original publication is available at http://www.springerlink.com/content/m2578mu420796236/