Integrating Protocol Modelling into an Aspect

Integrating Protocol Modelling into an
Aspect-Oriented Multi-View Modelling
Approach
Abir Ayed
abir.ayed [at] mail.mcgill.ca
MASTER OF SCIENCE
December 2013
Supervisor:
Prof. Jorg Kienzle, McGill University
Joerg.Kienzle [at] mcgill.ca
School of Computer Science, McGill University
Montreal, Canada
1
A thesis submitted to McGill University
in partial fulfillment of the requirements
of the degree of
Master of Science
Copyright © December 2013 by Abir Ayed
2
To My Parents
3
Abstract
The complexity of modern software makes its development, evolution and
maintenance difficult. Object-Oriented software development provides means
for reducing the complexity by decomposing software into modules with welldefined responsibilities. Unfortunately, the Object-Oriented paradigm reaches
its limitations when it comes to modularizing crosscutting concerns.
Aspect-Oriented Programming (AOP) addresses the separation of crosscutting concerns from the business logic on the source code level. Aspect-Oriented
Modelling (AOM) allows to do this on a higher level of abstraction where crosscutting concerns are addressed during earlier phases of the software development
process. Aspect-oriented modelling approaches advocate to model concerns separately, and then to use model composition to create complex models in which
these concerns are intertwined. In such a context, specifying the composition of
the models is a non-trivial task, in particular when it comes to specifying the
composition of behavioural models.
Reusable Aspect Models (RAM) is an aspect-oriented multi-view modelling
approach that allows detailed design of a software system. Notations similar
to UML class, sequence and state diagrams are used to describe the structure
and behaviour of a reusable aspect. Previously a meta-model and a weaver was
defined for the structural view (class diagram) and the message views (similar
to Sequence Diagrams) to be used in a tool for RAM. However, the state views
introduced in RAM were never formally defined.
In this thesis we describe how we added the definition of a behavioural view
to RAM - the state view - that specifies the allowed invocation protocol of
class instances. We discuss why Protocol Modelling, a compositional modelling
approach based on state diagrams, is an ideal notation to specify such a state
view, and show how we added support for protocol modelling to the RAM
metamodel. We present an algorithm to weave state views, and describe how
this algorithm is integrated with the weaving algorithms for the structural and
message views. We outline an implementation of the weaver in the context of
the Eclipse Modelling Framework, and explain how we extended TouchRAM,
the multitouch-enabled tool for the RAM approach, with support for creation
and weaving of state views.
4
Sommaire
La complexité des logiciels rend leurs développement, évolution et entretien difficile. Le développement orienté-objet des logiciels offre la possibilité de
réduire la complexité en décomposant le logiciel en modules avec des responsabilités bien définies. Malheureusement, le paradigme orienté-objet atteint ses
limites quand il est question de modélisation des préoccupations transversales
(crosscutting concerns).
La Programmation Orientée-Aspect (AOP) adresse la séparation de préoccupations transversales de la logique d’affaire au niveau du code source. La Modélisation Orientée-Aspect (AOM) permet de réaliser cet objectif avec un niveau
d’abstraction élevé en adressant ces préoccupations dès le début du processus
de développement logiciel. Les approches de modélisation orientée-aspect encourage à modéliser ces fonctionnalités séparément, et à utiliser dans une deuxième
étape des techniques de composition des modèles pour créer un modèle complexe dans lequel ces fonctionnalités seront entremêlées. Dans ce contexte, la
tâche de spécifier la composition des modèles n’est pas triviale, surtout quand
il s’agit de spécifications comportementales.
Reusable Aspect Models (RAM) est une approche multi-vue de modélisation aspect-orientée qui offre une conception détaillée du système logiciel. La
structure et le comportement d’un aspect réutilisable sont décrit avec des notations similaires à celles des diagrammes de classe, séquence et état de UML.
Antérieurement, un Méta-Modèle et un “tisseur” (ou “Weaver” en Anglais), cad
un composant permettant de composer des aspects ensembles, ont été définis
pour la vue structurelle (diagramme de classe) et les vues des messages (similaire au diagramme de séquence) pour les utiliser dans l’outil conçu pour RAM.
Cependant, les vues d’états introduites théoriquement dans RAM en 2009 n’ont
jamais été définies formellement.
Dans cette thèse on décrit comment la définition d’une vue comportementale a été ajoutée à RAM - la vue d’état - qui spécifie le protocole d’invocation
permise pour les instances d’une classe. Nous présentons pourquoi la Modélisation des Protocoles (Protocol Modelling (PM)), une approche de modélisation
de composition basée sur les diagrammes d’état, est une notation idéale pour
spécifier une telle vue, et nous décrivons comment nous avons procédé à l’ajout
du support de PM au méta-modèle existant de RAM. Un algorithme pour le
tissage des vues d’état est détaillé, et un processus générale de fusion, qui inclut
tous les vues, a été défini. Le tisseur pour les vues d’état a été développé dans
le contexte du Eclipse Modelling Framework (EMF). Finalement, l’outil tactile
pour RAM, TouchRAM, a été étendu pour offrir la création et la fusion des
vues d’état.
5
Acknowledgements
I would like to express my gratitude to my supervisor, Prof. Jorg Kienzle, whose expertise, understanding, and patience, added considerably to my
graduate experience. I appreciate all his time and effort while supervising my
thesis.
I would also like to thank my family for the support they provided me
through my entire life and without whose love and encouragement I would not
have finished this thesis.
Thank you.
6
Contents
I
Introduction
9
II
Background
13
1 AOSD
13
1.1 AOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.2 AOP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2 RAM
2.1 General Structure . . . . . . .
2.1.1 Structural View . . . .
2.1.2 Message View . . . .
2.1.3 Old State View . . . .
2.2 Modelling with RAM . . . . .
2.3 Stock Exchange Example . .
2.3.1 Model Customization
2.3.2 Model Extension . . .
2.3.3 Weaving . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15
15
16
17
17
18
19
19
21
23
III State View Definition (Specifying invocation Protocols)
27
3 Requirements
4 Related Work
4.1 UML . . . . . . . .
4.2 Mahoney et al. . . .
4.3 The Motorola Weavr
4.4 HILA . . . . . . . .
4.5 Protocol Modelling
28
. . . . . . . . . . . . .
. . . . . . . . . . . . .
Approach of Cottenier
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . .
. . . .
et al. .
. . . .
. . . .
5 Specifying RAM state view with PM
5.1 General Overview . . . . . . . . . . . . . . . . .
5.2 Using RAM State Views . . . . . . . . . . . . .
5.2.1 State Views for Public Operations . . .
5.2.2 Internal State Views . . . . . . . . . . .
5.3 Discussion . . . . . . . . . . . . . . . . . . . . .
5.4 Differences between PM and RAM state views
7
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
29
29
32
33
33
34
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
36
36
38
39
40
42
46
IV
Metamodel for State Views
48
6 Overview of UML State Machine Metamodel
7 Current Metamodel
7.1 Overview . . . .
7.2 Structural View .
7.3 Message View . .
48
of RAM
51
. . . . . . . . . . . . . . . . . . . . . . . . . . . 51
. . . . . . . . . . . . . . . . . . . . . . . . . . . 52
. . . . . . . . . . . . . . . . . . . . . . . . . . . 53
8 New RAM State View Metamodel
53
V
56
State View Weaving
9 Weaving Structural Views
56
10 Weaving State Views
10.1 State View Weaving Algorithm
10.1.1 General Overview . . .
10.1.2 Copying State Views . .
10.1.3 Weaving . . . . . . . . .
VI
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
State View Support for TouchRAM
11 Overview of TouchRAM
11.1 Frameworks Used by TouchRAM .
11.1.1 Eclipse Modelling Framework
11.1.2 Multitouch for Java (MT4j) .
11.2 TouchRAM Implementation . . . .
59
59
59
61
63
67
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
67
67
67
68
69
12 Integration of State Views into TouchRAM
12.1 State View GUI . . . . . . . . . . . . . . . . . .
12.1.1 Views . . . . . . . . . . . . . . . . . . .
12.1.2 Handlers . . . . . . . . . . . . . . . . . .
12.1.3 Layouts . . . . . . . . . . . . . . . . . .
12.2 State View Controller . . . . . . . . . . . . . .
12.3 State View Weaver . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
69
70
71
71
71
72
72
VII
.
.
.
.
Conclusion And Future Work
Appendix
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
75
78
8
Part I
Introduction
The complexity of a software makes its development, evolution and maintenance difficult. Without software engineering processes, methodologies and
tools developing a high-quality, evolving software would be a nightmare. The
object-oriented paradigm (OO) [28] is considered one of the most important
contributions in the history of software development. It focuses on developing
a technique to decompose a software into small modules and treat each module
in isolation to simplify the problem.
The unit of modularization in OO is the object, and when applying OO to
decompose a problem or solution into units, all concerns of that problem or
solution have to be mapped to objects. Unfortunately some crosscutting concerns can not be modularized using this kind of separation. Examples of such
concerns are logging, security, and synchronization. As a result, bits and pieces
of structural and behavioural properties related to these crosscutting functionalities are usually found scattered across multiple objects. Implementing such
crosscutting concerns results first in a poor modularization, which makes software maintenance and evolution harder, and second in code tangling, which
reduces the reusability of the modules that contain multiple different concerns.
Aspect-Oriented Software Development is an emerging paradigm that introduces a new way to modularize a software by providing techniques to identify,
separate, and also compose crosscutting concerns. The goal is to increase maintainability and reusability of software artifacts by means of clear separation of
concerns. With AOSD techniques, crosscutting concerns can be defined in one
place and the specific points in the software system where they should be applied can be indicated when the concern is reused. When the final application is
created, the concerns are woven into the application at the appropriate places.
While Aspect-Oriented Programming (AOP) [22] provides this technique at
the source code level, Aspect-Oriented Modelling (AOM) aims to define aspects
at a higher level of abstraction, which allows a consistent use throughout the
software development process. AOM techniques often make use of the Unified
Modelling Language (UML) [19].
At the software design level, for instance, aspect-oriented modelling approaches make it possible to clearly modularize software design concerns. This
enables a modeller to express the design of a complex system by modelling
different small design concerns in separate models. These interdependent and
small models can later be composed / woven together to obtain the integrated
design of the complex system.
Unfortunately, the complexity of understanding the wanted or unwanted
dependencies and the interactions between concern models is one of the major
issues of this technique. As an example, imagine the transaction and logging
concerns. With transactions, a set of operations can be made atomic, which
means that the execution of the operations inside the transaction are seen from
9
the outside as one indivisible operation. Logging is used to track the execution
of operations. When combining both concerns, the order of application to the
business logic concern is important, i.e., logging should not keep track of the
execution of the inner operations of a transaction.
Thus, being able to understand the interactions between all concern models
that form a complex system to ensure that the resulting behaviour is correct is
not an easy task. Especially behavioural composition has been a subject of study
for many years now [29], and recognized as a major problem in aspect-oriented
software development.
RAM is a promising multi-view aspect-oriented modelling approach that
allows a developer to describe a system under development from multiple points
of view using different modelling notations. It leverages three views for each
concern: a structural view of the system described with class diagrams and two
behavioural views, state and message view, described respectively with state
and sequence diagrams, that specify the behaviour of the methods defined in
the class diagrams.
Behavioural composition of sequence diagrams in RAM is asymmetric in nature. One sequence diagram can invoke an operation that is defined by another
sequence diagram, which means that the weaver has to insert the behaviour of
the called operation into the sequence diagram that made the call. Furthermore, aspect message views can modify the behaviour of a sequence diagrams
by adding additional behaviour before or after the already existing sequence of
interactions. To understand the resulting behaviour becomes tricky, in particular if the different behavioural specifications are scattered over multiple models.
Also, as for all asymmetric approaches, the order of composition matters in the
case where several aspect models want to add behaviour at the same place.
To aid the modeller in designing complex aspect-oriented behavioural specifications, and to provide a concrete way to check the correctness of the composed
model behaviour, state views were introduced into RAM. State views provide a
second behavioural notation with which the behaviour described by the message
view can be validated.
A metamodel for RAM containing the structural view and message views
of aspects already exists. Furthermore, an algorithm for weaving the structure
and the message views of RAM models together to produce a final woven model
was designed and implemented. A graphical tool named TouchRAM [31] has
been developed. It allows modellers to create and edit structural views, and it
is capable of visualizing message views. A modeller can ask the tool to weave
RAM models together and visualize the woven result.
So far though, state views for RAM are not formally defined (i.e., the RAM
metamodel used in the TouchRAM tool does not include them). The paper that
introduced state views [5] simply uses standard UML state diagrams as message
views without discussing if all UML state diagram features are supported, for
instance. Furthermore, no detailed weaving algorithm has been described in [5]
for state views. Actually, state view weaving was so far done by hand in an ad
hoc way. As a result, modelling with state views was clumsy at best. As a result,
most comprehensive case studies conducted with RAM simply disregarded state
10
views.
The goal of this thesis is to reflect on the properties that a modelling notation for state views should have, and based on those find the most adequate,
compositional, state-based modelling notation and integrate it into RAM. This
required the definition of a metamodel for state views, the development of a
weaving algorithm for state views, and the extension of the TouchRAM tool to
support the creation and editing of state views as well as invoking the weaving
algorithm. Having support for state views in the RAM metamodel and being
able to compose individual state views together to build the complete protocol for design classes prepares the ground for the TouchRAM tool to then be
able to perform consistency checking of behavioural specifications across model
boundaries, i.e., between interdependent aspect models.
Concretely, the main contributions of this thesis are as follows:
• State view metamodel: A metamodel for state views has been defined and
integrated into the existing metamodel.
– A list of the different requirements that the RAM state view should
fulfil has been defined.
– Different frameworks using state/transition notation have been studied and analysed.
– The existing RAM metamodel has been adapted to integrate a simplified form of the Protocol Modelling approach into RAM.
• Weaving of state views: An algorithm for state view weaving was specified.
– An algorithm to weave state views has been defined.
– State view weaving has been conceptually integrated with structural
and message view weaving.
• State view support for the TouchRAM tool: TouchRAM was extended
to support state views.
– The TouchRAM GUI has been augmented with a state view that
allows for the creation and editing of state views.
– The state view weaver has been implemented.
– State views can be woven in TouchRAM and the woven result
viewed.
– Suggestions on how state views could be weaved according to the
modeller needs have been presented.
The paper is structured as follows. Chapter II presents background information
on aspect-orientation and a detailed overview of the Reusable Aspect Models
approach. Chapter III enumerates the requirements we identified for a modelling
notation to be adequate for use as a state view, and presents some related work
11
and how a restricted form of PM is used to specify this view. Chapter IV gives
an overview of RAM metamodel and describes how it was modified to support
the integration of PM. Chapter V provides an overview on how weaving of
state views works and explains the formalized weaving algorithm. Chapter VI
presents an overview of TouchRAM tool and how the state view creation and
weaving was integrated to it. The last chapter concludes this paper and presents
some thoughts on future work.
12
Part II
Background
1
AOSD
Despite the fact that separation of concerns is a long-established principle in
software engineering that received a widespread attention with constructs such
as packages, classes, interfaces, etc., problems with inadequate separation of
concerns remain [20]. This issue has been studied in different works including
subject-oriented programming [7] and design, aspect-oriented programming [22]
and multi-dimensional separation of concerns [32]. These different approaches
and ideas help improving programming languages in particular and software
development in general.
Aspect-oriented software development (AOSD) is an emerging software development technology that encompasses these innovative ideas in order to increase maintainability and reusability.
This methodology seeks to achieve its goal by trying to improve one of the
drawbacks of the traditional development techniques i.e. it seeks to define a new
kind of modularizations of software systems. Traditional techniques as objectoriented software development have the tendency to decompose and modularize
a software into functional modules. This kind of modularity imposes unwanted
constraints on the design and leads to scattering and tangling as code for some
concern crosscuts multiple parts of the system [8].
AOSD defined a new way to modularize separately crosscutting-concerns,
i.e., logging, security, synchronization concerns, etc. and to integrate and weave
these concerns within a software system. It initially started at the programming
level with Aspect-Oriented Programming (AOP). After the positive results noticed with this approach, researchers, during the last few years, exported this
idea to different levels of the software development process like User Requirements Definition[15] and Modelling and Design phases.
1.1
AOM
A model in general is used to analyze, understand and sometimes control a complex system. It simplifies an environment and focuses on a specific concern of
this environment. In the case of software modelling, the software domain represents this environment. In this context, Aspect-Oriented Modelling (AOM) is an
early phase of an AOSD where a general overview and a better understanding
of the software is created. This phase addresses specifically the identification
and definition of cross-cutting concerns on different level of abstraction. It can
be used for high-level requirements models, for architectural or high-level design models, and also for detailed design. AOM represents the deployment of
AOSD technology early in the software life cycle to use the technology to its full
potential and significantly enhance support for separation of concerns. Identi13
fying system components in the modelling stage has the benefit of making these
components more reusable and automatic code generation possible for AOP systems [11]. Furthermore, consistency between requirements, design and code is
maintained when applying AO design within the development life cycle [9].
A model can describe a system from multiple views using different diagrams.
The Unified Modelling Language (UML) is the standard modelling language for
object-oriented software systems. Since it is a known and a mature language, it
was natural that in the modelling community some work on describing aspectoriented programs has been often based on this language. Multidimensional separation of concerns is supported by modelling languages such as UML through
the use of different diagrams that can be used to describe nonorthogonal views of
a system. Enhancing an OO notation such as UML with AO techniques makes
it possible to elegantly modularize crosscutting concerns within individual views
1.2
AOP
Software design processes and programming languages complement each other.
Design process defines the different modules and small units of the software system while a programming language provide mechanisms to create these units
and to compose them together in different ways to produce the complete system.
The relationship between the design process and the programming language can
be successful only when the programming language provides the support necessary to cleanly implement the different units defined in the design process [22].
Aspect-Oriented Programming (AOP) is the implementation of the AOSD
discipline at the level of source code. It is a programming paradigm that offers methods and tools to separate the crosscutting concerns from the program
functional business logic. Such languages allow developers to program crosscutting aspects in one place and and then automatically propagate and inject the
behaviour to the many appropriate points of execution in the code.
Many programming languages have adopted this paradigm and implemented
it within or as a separate library, among them Smalltalk and Java. The Java
implementation of AOP, AspectJ[2] , is probably the most mature and fully
featured framework available today.
AspectJ extends Java through additional keywords to support AOP concepts, similar to the way C++ extended C to support OOP concepts.
The AOP model has different crosscutting constructs that can be classified
common (join point, pointcut and aspect), dynamic (inter-type and weave-time
declarations) and static [2]. Join points are the places where crosscutting actions
take place. A pointcut is a program construct that selects join points and collects
context at those points. An aspect is the central unit in AspectJ, as it is the
case with a class in Java. It contains the weaving rules for both dynamic and
static crosscutting and can contain also data, methods, etc. Advice is the code
executed at a join point selected by a pointcut. It can execute before, after, or
around (meaning instead of ) the join point.
14
2
RAM
In RAM, the model of a concern or functionality contains up to two different
kinds of views – a structural view and message views – which are grouped
together in a package. These views are described with two extended diagram
notations from the Unified Modelling Language (UML), namely class diagrams
and sequence diagrams.
RAM is a modelling approach, in which there is no distinction between an
aspect or base model. Every concern or functionality of a software system is
described by a RAM model. One of the main goals of high importance is to
achieve a high level of reusability. Aspects in RAM are defined as general as
possible, and mechanisms are provided to reuse functionality of existing aspects.
This allows high-level aspects to be decomposed into lower-level aspects and
other aspects can reuse their functionality as well. Besides, aspects can be
shared across applications.
RAM aspect models define an aspect interface that clearly designates the
functionality provided by the aspect. Every public operation is part of the aspect
interface. When an aspect in RAM wants to reuse the functionality of existing
aspects this is done by instantiating that aspect. Aspects in RAM are aware
of what functionality they are extended by. Therefore, they are not oblivious
as described by Filman and Friedman [16]. In [16] they state the definition of
AOP as being quantification and obliviousness. However, when building large
applications with AOP, changing a pointcut can lead to unwanted effects (the
“fragile pointcut” problem). The results become unpredictable as too many
elements could be affected by a slight change in a pointcut. For this reason, it
is commonly accepted that obliviousness is not an essential property of AO but
a useful one [1].
Combining several aspects might lead to conflicts when several changes in
the behaviour or structure are required by different aspects. For this case, RAM
offers conflict resolution aspects where the resolution of conflicts between two
aspects can be separately defined.
2.1
General Structure
In RAM, each design concern of a software system is encapsulated in a package
with the three views. Each view describes and provides a different information
about the concern.
A package has a header followed by the compartment of the structure view
and multiple compartments of the message view - at least one message view per
public operation defined in the structure view. In the header the name of the
concern is specified after the keyword “aspect”.
ZeroToMany-Ordered Fig. 1 describes a RAM model called ZeroToMany-Ordered,
which defines an association between two classes, i.e. Data and Associated
using composition with a multiplicity of 0..*, while abstracting away some
implementation information, i.e., the association between the two classes
is implemented through the use of the class Sequence.
15
aspect ZeroToMany-Ordered
|Data
|Associated
structural view
|Data
Sequence
int size
+ |Data |Data()
+ add(|Associated a)
+ remove(|Associated a)
+ |Associated get(int index)
+ boolean contains(|Associated a)
+ Sequence<|Associated> getAssociated()
+ int getSize()
Implementation:
Sequence:
|Associated
int size
~ Sequence Sequence()
1 ~ add(|Associated a)
mySeq ~ remove(|Associated a)
~ |Associated get(int index)
~ boolean contains(|Associated)
~ destroy()
0..*
|Associated
any java.util.List
message view |Data affected by initializeAssociation
message view initializeAssociation
caller: Caller
Pointcut
Advice
caller:
Caller
new := |Data(..)
new := |Data(..)
new:
|Data
new:
|Data
*
*
message view add(|Associated)
target: |Data
caller: Caller
add(a)
mySeq := Sequence()
mySeq:
Sequence
<|Associated>
mySeq:
Sequence<|Associated>
add(a)
Figure 1: ZeroToMany-Ordered RAM Model
2.1.1
Structural View
The structural view is the first compartment of a RAM model. It allows a
modeller to specify the static structure of the software design concern that is
modelled, i.e., the classes with their attributes and operations and the associations among classes. It is expressed using a UML class diagram.
The structure view of the concern ZeroToMany-Ordered (Fig. 1) defines a
class |Data, which uses a Sequence to link an instance of |Data to many instances of the class |Associated in an ordered way. RAM allows to reuse existing classes provided by the programming language or frameworks being used, for
example the class Sequence refers to a Java implementation of java.util.List
as specified in the implementation section of the package.
The ZeroToMany-Ordered concern is a general aspect that can be reused by
any other model that needs its functionality. To increase the reusability of models, RAM offers the modeller the possibility to create aspects as parameterized
templates using the concept of partiality: partial classes and partial operations.
A partial entity in a generic concern is an element that is incomplete by itself
and needs to be mapped to another element from the application specific aspect
when this concern is used. A partial element is identified by a vertical bar ’|’
next to its name.
|Data and |Associated are partial classes, i.e., incomplete classes, that
must be mapped to another class whenever the model is used within another
16
model. These classes are partial since at this point is not yet known what actual
application classes will need to be associated with each other. Any model that
wants to use the generic ZeroToMany-Ordered model must map |Data and
|Associated to two of its classes.
In the upper right corner of an aspect mandatory instantiation parameters
are listed to point out to the modeller that these entities need to be mapped
in order to use this aspect. The set of mandatory instantiation parameters is
called the customization interface.
In RAM there are three types of visibility modifiers for operations: public
(+), private (-) and aspect private (~). All public operations are part of the
usage interface of a RAM model, i.e., they are the operations that another model
can invoke to trigger the behaviour of ZeroToMany-Ordered. Private operations
can only be invoked from within the same class, and aspect-private operations
can be called only by classes included in the same RAM model.
2.1.2
Message View
Message views describe the behaviour of the concern being modelled. There is
one message view for each public operation defined by a class in the structural
view. Each message view describes the sequencing of message interchanges that
occur between instances of classes of the concern when providing the functionality offered by the public operation.
In the ZeroToMany-Ordered model, the class |Data has eight public operations. All these operations involve interactions with an instance of the class
Sequence. For space reasons, Fig. 1 only shows the message view for the constructor of |Data() and one for the add operation. The message view of the
constructor is an aspect message view, i.e., composed of a pointcut and an advice. It specifies that whenever a |Data instance is created (in the pointcut) the
behaviour described in the advice has to be executed. In this case, the behaviour
is added after the original behaviour (represented by a box with the character ’*’
inside). The Sequence of |Associated will be created and stored in the property mySeq. The message view of the public operation add(|Associated a) is
a normal message view that specifies that whenever this operation is invoked
the call is forwarded to the Sequence instance by calling its add(|Associated
a) operation. In addition, behaviour from instantiated aspects can be extended
or replaced.
2.1.3
Old State View
In [23], state views were introduced into RAM, which allow a modeller to specify
an operation invocation protocol for instance of classes of the structural view.
The main idea was that this additional behavioural view would make it possible
to verify the consistency of behavioural specifications in RAM when they cross
model boundaries, as well as to model-check composed behavioural specifications
by comparing the woven sequence diagrams and state diagrams with each other.
17
However, the state views introduced in [23] were never formally defined. The
presented examples used the syntax of UML state diagrams, but it was never
clearly stated if all advanced features of UML state diagrams are supported
(for example, hierarchy, history states, etc.). Finally, and most importantly,
the composition mechanism for state views was never precisely defined. Case
studies showed that simple state merge would not be sufficient to express the
changes in protocol that complex sequence diagram compositions can produce.
Proposed solutions (mapping states to substates, orthogonal states and even
concurrent states) were complex, and the semantics sometimes unclear. It is for
this reason that we decided to look for a new modelling notation that can be
used for RAM state views as described in the following sections.
2.2
Modelling with RAM
RAM allows a modeller to build complex models of any size by putting together
many interdependent, simple models. This is achieved through model hierarchies and model increments. To use the functionality provided by a (base) RAM
model B within the design of a model A, the designer must specify instantiation
directives that map all mandatory instantiation parameters of the customization
interface of B to model elements of A. Using these directives, the TouchRAM
tool can compose both models to yield a “woven” model that combines the model
elements from both designs.
RAM supports two kinds of model dependencies, model extensions and model
customizations.
Model Extension: When A extends B, the modeller’s intent is to add additional structural and/or behavioural model elements to B that provide
additional, alternative or complementary properties to what already exists in B. The extension model A augments the public interface of the base
model B with additional structure and behaviour. A is also allowed to use
the private model elements of B to integrate with the base model. Model
extensions make it possible to build a complex design concern with many
classes offering lots of functionality by incrementally composing several
RAM models.
Model Customization: A customization is useful when a modeller’s intent is
to adapt the structure and behaviour provided by a base model B to be
useful in a specific context. Within a customization model A, a modeller
alters or augments existing base model properties to render them useful
for a new purpose. Customization is typically used when the model A
specifies a higher-level design concern that internally uses the lower-level
design concern B to implement some of its functionality. In this case, A is
only allowed to use the public model elements of B. Also, the usage of B
is usually completely hidden within A. In other words, the public model
elements of B become private elements of A.
For the rest of the paper, we will distinguish three kinds of modellers for a given
18
RAM model M. Model designers (of M) are the modellers that specify the structural, message and state views of M. Modellers that use customization to include
the design details provided by M within a higher-level model are called model
users (of M ). Modellers that use extensions to increment M with additional
features described in a separate RAM model are called model incrementers (of
M ).
2.3
Stock Exchange Example
For a better understanding of RAM we will use a simple example aspect to
show how complex models can be built. We will explain a small part of a
stock exchange application which uses the Observer design pattern [14]. The
StockExchange aspect defines a stock class and a stock window that can be
used to display the state of stock instances.
2.3.1
Model Customization
The Observer design pattern defines an observer that is able to register itself on a subject (or observable objects). Each subject can be observed by
many observers. Whenever the subject gets modified it notifies all registered
observers that it was updated. This is a lower-level functionality and can be
reused several times in an application. The Observer pattern is defined as
an aspect model allowing it to be used by other aspects or applications as
well. The aspect Observer, however, depends on the even lower-level aspect
ZeroToMany-Ordered (Fig. 1) to handle the list of the observers.
Observer The definition of the aspect Observer is shown in Fig. 2. It defines a
class |Observer that can observe one |Subject. In addition to operations,
that allow the start and stop of observing a subject, it defines |update
which allows the subject to notify the observer about changes. |Subject
defines an operation |modify. Both operations are partial meaning that
aspects that want to use the Observer aspect have to specify concrete operations that modify the subject and an operation that allows the observer
to update by providing mappings. The association between a |Subject
being observed by many |Observers is introduced through instantiating
the ZeroToMany-Ordered aspect.
When instantiating an aspect to use its functionality, the visibility of its
elements is subject to modifications depending on the kind of instantiation. In
the case of depends instantiation (model customization), the modeller has to
provide mappings for all elements that should be exposed at the higher level.
The visibility of unmapped elements is changed from public to aspect-private [3].
However, in the case of extends instantiation (model extension), the visibility
of the elements from the instantiated aspect stay intact.
Mappings are specified in the instantiation section in the form of:
lower_Level_Aspect_Element → high_Level_Aspect_Element
19
aspect Observer depends on ZeroToMany-Ordered
structural view
|Subject
~ Set<|Observer> getObservers()
+ * |modify(..)
~ notifyObservers()
Instantiations:
ZeroToMany:
|Subject
|Observer
|modify
|update
|Observer
mySubject
0..1
+ startObserving(|Subject)
+ stopObserving()
~ |update(|Subject)
|Data → |Subject; |Associated → |Observer; getAssociated → getObservers
message view startObserving
target: |Observer
caller: Caller
s: |Subject
startObserving(s)
add(target)
Default Instantiation: caller → *; Caller → *; new → *
message view stopObserving
target: |Observer
caller: Caller
stopObserving()
remove(target)
Default Instantiation: caller → *; Caller → *; new → *
message view |modify affected by notification
message view notification
caller: Caller
Advice
target: |Subject
caller: Caller
|modify(..)
target: |Subject
|modify(..)
*
*
notifyObservers()
Pointcut
Default Instantiation: caller → *; Caller → *; new → *
message view notifyObservers
mySubject:
|Subject
target: |Subject
notifyObservers()
observers := getObservers()
loop [o within observers]
o: |Observer
|update(target)
Figure 2: The Observer RAM Model.
20
An element from the lower level aspect can be mapped to many elements of
the higher level aspect.
The aspect Observer depends on the aspect ZeroToMany-Ordered.For this
reason mandatory instantiation parameters of the latter aspect should be provided. In the instantiation section of Fig. 2, |Data is mapped to |Subject and
|Associated is mapped to |Observer.
ZeroToMany-Ordered and Observer are incomplete models or in other word
they are not application-specific models. The concept of partiality and mandatory instantiation make them more generic and therefor easier to reuse. The
next step will be to show through the example of the StockExchange model how
application-specific aspects can take advantage of the functionality provided by
partial ones.
StockExchange The design of the aspect StockExchange is shown in Fig. 3. It
defines a Stock which has a name and a price and corresponding getter
and setter operations. A StockWindow’s task is to display the information
of a stock. Therefore, it defines the operation updateWindow that can be
called to request the window to update the information of the stock.
In order for a StockWindow to be able to receive updates whenever the Stock
was modified, the modeller reuses Observer as this already existing aspect provides the required functionality. Since the StockWindow should be updated
whenever a stock changes, the |Subject is mapped to Stock and |Observer to
StockWindow. A Stock is modified by the setters, hence |modify is mapped to
setName and setPrice. For StockWindow, |update is mapped to updateWindow,
as it is the operation that should be called to request the window to update itself.
2.3.2
Model Extension
After showing how a model can be customized in RAM using the example
StockExchange and Observer and the example of Observer and ZeroToManyOrdered, this section will show how a model can be extended in RAM. We
will consider the example of StockExchangeGraph, an extended version of the
StockExchange model.
StockExchangeGraph model keeps track of the stock changes over time, and
offers the functionality of generating a stock price graph over time. It
uses both kinds of model dependencies. On the one hand it depends on
Traceable and ZeroToMany-Ordered to handle and manage the creation
and the storing of the stock changes. on the other hand it extends the
basic functionalities provided by the StockExchange model.
Traceable Fig. 4 shows the definition of the Traceable model. This aspect provides objects with the functionality of tracing the execution of their operations. It defines a complete class Trace and a partial class |Traceable that
represents the entity to be traced. When Traceable is used, |Traceable
class should be mapped to concrete class C and the methods that their
execution should be traced in the class C should be mapped to the partial
21
aspect StockExchange depends on Observer
structural view
Stock
- String name
- int price
+ Stock Stock(String name, int price)
+ String getName()
+ String setName()
+ setPrice(int price)
+ int getPrice()
StockWindow
+ StockWindow StockWindow(Stock s)
~ updateWindow(Stock s)
Instantiations:
Observer:
|Subject → Stock; |Observer → StockWindow;
|modify → setPrice, setName; |update → updateWindow;
message view Stock.Stock
Stock(String name, int price)
target: Stock
setName(name)
setPrice(price)
message view StockWindow.create
StockWindow(Stock s)
target:
StockWindow
mySubject := s
message view Stock.getName() is Getter<name>
message view Stock.setName() is Setter<name>
message view Stock.getPrice() is Getter<price>
message view Stock.setPrice() is Setter<price>
Figure 3: The StockExchange RAM Model.
22
aspect Traceable
structural view
<<impl>>
Method
1
invokedMethod
<<enumeration>>
AccessKind
Read
Write
Update
|Traceable,
|traceableMethod<AccessKind>
Trace
- AccessKind kind
- Int time
~ Trace(Method invokedMethod,
AccessKind kind, |Traceable target)
+ |Traceable getTarget()
+ AccessKind getAccessKind()
+ getTime()
|Traceable
1 target + Trace createTrace(Method)
+ * |traceableMethod<AccessKind>(..)
Implementation:
Method:
java.lang.reflect.Method
message view createTrace
target: |Traceable
createTrace(m)
accessKind := getAccessKind(m)
result := Trace(m, accessKind, target)
|newT: Trace
message view getTarget is Getter<target>
message view getAccessKind is Getter<kind>
Figure 4: The Traceable RAM Model.
operation |traceableMethod. Notice the existence of an implementation
section in the model, Traceable reuses the implementation of the class
Method provided by the Java programming language.
The StockExchangeGraph is depicted in Fig. 5. As mentioned before and as
shown in the header, it extends StockExchange and depends on Traceable and
ZeroToMany-Ordered. It extends StockExchange by introducing new methods
to the class Stock and by introducing a new class StockGraph. In RAM a static
method is distinguished by being underlined. StockGraph has a static method
Plot(List<Trace> traces) that provided by a list of traces is able to plot the
stock price in the y-axis and the time of day in the x-axis. To keep track of
the price changes, StockExchangeGraph uses the functionalities provided by the
Traceable aspect. Since the aim is to trace the changes undergone by a stock,
which are triggered by the setters methods, |Traceable was mapped to Stock
and |traceableMethod to both setName and setPrice. ZeroToMany-Ordered
was used to store the traces of a Stock.
2.3.3
Weaving
The structural view as well as the message views of aspects can be woven in
RAM using a tool. The weaver in RAM merges dependant models together
to give the modeller a view of the complete model. It allows to weave aspect
hierarchies of arbitrary depth. The designer is given the choice to either weave
all the aspect within a hierarchy, i.e., all the low-level models that the aspect
depends on are combined, or to weave two specific aspects together that are
directly dependent. This allows the modeller to see the result of instantiating
an aspect and ensure that the resulting structure and behaviour is the way it is
intended to be.
Fig. 6 shows an overview of the StockExchangeGraph hierarchy. Using the
23
aspect StockExchangeGraph extends StockExchange depends on Traceable, ZeroToMany-Ordered
structural view
Stock
Trace
StockGraph
- String name
- int price
+ Stock Stock(String name, int price)
+ String setName()
+ setPrice(int price)
+ boolean wasModified()
+ Sequence<Trace> getTraces()
+ addTrace(Trace trace)
+ Plot(Stock stock)
Instantiations:
Traceable:
|Traceable → Stock; |traceableMethod → setPrice; |traceableMethod → setName; Trace →
Trace;
ZeroToMany-Ordered: |Data → Stock; |Associated → Trace; getAssociated → getTraces; add → addTrace;
Figure 5: The StockExchangeGraph RAM Model.
StockExchangeGraph
Traceable
StockExchange
Observer
ZeroToMany-Ordered
Figure 6: StockExchangeGraph Dependencies.
RAM tool the modeller is able to weave the five models together to get a
complete overview of the structure and behaviour of the StockExchangeGraph
model.
When weaving, for each entity that has a mapping, the appropriate modification is applied to it otherwise it is added as is to the model. Fig. 7 shows the
complete woven model of StockExchangeGraph. The result is an independent
model. The following paragraphs give an overview of how Fig. 7 was created.
When Observer and ZeroToMany-Ordered got merged with the StockExchange
model:
• |Data (from ZeroToMany-Ordered) was merged first with |Subject (from
Observer). As a result all the methods from |Data were copied into
|Subject. Following the instantiation directives, the getAssociated method
was renamed to getObservers and its visibility changed from public to
package-private. |Data was then merged with Stock, thus all the methods from |Subject were copied to Stock and the |modify method was
duplicated and renamed to setName and setPrice.
• The |Associated class was mapped to |Observer, and since the former
does not contain any element the merge resulted in |Observer unchanged.
24
|Observer was later merged with StockWindow, where the |update method
was renamed to updateWindow.
• The Sequence class is an unmapped element, hence it was copied as it
is. The only change in this class is the fact that it is now applied to
StockWindow rather than to |Associated.
When Traceable and StockExchangeGraph got woven:
• |Traceable and Stock were merged, and the createTrace method was
added to Stock and the |traceableMethod was duplicated and renamed
to setName and setPrice.
• All the methods from Trace in Traceable were copied to Trace in Stock,
and all the references to |Traceable were updated to Stock. The unmapped elements, i.e. AccessKind and Method, were copied over.
Weaving ZeroToMany-Ordered and StockExchangeGraph resulted in merging
|Data with Stock and |Associated with Trace, and copying the class Sequence
over.
At last, weaving StockExchange with StockExchangeGraph resulted in augmenting the public interface of the base model StockExchange by adding the
method wasModified to Stock and introducing the new class StockGraph.
An overview of the algorithm used to generate an independent model, as
shown in 7, is presented in section 9.
25
aspect StockExchangeGraph
structural view
Stock
- String name
- int price
+ Stock Stock(String name, int price)
+ String getName()
+ String setName()
+ setPrice(int price)
+ int getPrice()
+ Trace createTrace(Method)
+ Sequence<Trace> getTraces()
+ addTrace(Trace trace)
+ boolean wasModified()
~ remove(Trace trace)
~ boolean contains(Trace observer)
~ Sequence<StockWindow> getObservers()
~ add(StockWindow observer)
~ remove(StockWindow observer)
~ boolean contains(StockWindow observer)
~ destroy()
1
StockWindow
mySubject
+ StockWindow StockWindow(Stock s)
~ updateWindow(Stock s)
~ startObserving(Stock s)
~ stopObserving()
0..1
0..*
Sequence
StockWindow
- int size
~ Sequence Sequence()
~ add(StockWindow)
~ boolean remove(StockWindow)
~ boolean contains(StockWindow)
~ destroy()
...
1 myObservers
target
Trace
1 myTraces
Sequence
Trace
- AccessKind kind
- Int time
~ Trace(Method invokedMethod,
AccessKind kind, Stock target)
+ Stock getTarget()
+ AccessKind getAccessKind()
+ getTime()
- int size
~ Sequence Sequence()
~ add(Trace)
~ boolean remove(Trace)
~ boolean contains(Trace)
~ destroy()
...
1
invokedMethod
<<impl>>
Method
<<enumeration>>
AccessKind
StockGraph
+ Plot(Stock stock)
Read
Write
Update
Implementation:
Method:
java.lang.reflect.Method
Figure 7: The structural view of the woven StockExchangeGraph Model.
26
Part III
State View Definition (Specifying
invocation Protocols)
As shown in 2.2, RAM allows a modeller to build complex models of any size
by composing many interdependent, simple models with so-called instantiation
directives that map model elements from one model to the other. As a result,
model hierarchies can be created, where models describing high-level design
concerns internally depend on models that describe low-level design concerns.
It is also possible to model complex design concerns incrementally by composing
several small models using instantiation directives. Specifying the composition
of RAM models using instantiation directives is a non-trivial task, in particular
when it comes to specifying the composition of behaviour.
Structural composition of class diagrams in RAM boils down to merging
of model elements. For two classes, for instance, this yields a new class that
has the properties from both of the merged classes. Experience shows that the
symmetric merge operation is conceptually easy to master by modellers.
Behavioural composition of sequence diagrams in RAM is asymmetric in nature. One sequence diagram can invoke an operation that is defined by another
sequence diagram, which means that the weaver has to insert the behaviour of
the called operation into the sequence diagram that made the call. Furthermore, aspect message views can modify the behaviour of an existing sequence
diagram by adding additional behaviour before or after the already existing sequence of interactions. To understand the resulting behaviour becomes tricky,
in particular if many interacting behavioural specifications are scattered in multiple models. Also, as for all asymmetric approaches, the order of composition
matters in the case where several aspect models want to add behaviour at the
same place.
To address the behavioural composition issues and the complexity of understanding aspect dependencies and interactions we decided to add to RAM a new
behavioural view that complements message views. This new view can be used
for both documentation and validation purposes.
Documentation wise, it can serve as an additional description for the model
user to provide him a clear understanding of the behaviour of an aspect. Thus,
decreasing the probability of making mistakes when customizing and extending
the model. Specifying the relationship between the operations belonging to the
same object and defining the allowed invocation protocol of class instances is
the missing information that will help having a more complete description of
model behaviours in RAM.
Validation wise, it should make it possible to verify the consistency of behavioural specifications in RAM when they cross model boundaries, as well as
to model-check composed behavioural specifications by comparing the woven
message views and the new view with each other.
27
In this section we first list the requirements that a modelling notation needs
to fulfil in order to be useful in the context of RAM for the above mentioned
purpose. Then, we briefly present the Protocol Modelling approach (PM), and
show how we adapted it to fit our needs.
3
Requirements
Based on the experience gained from creating several complex software designs
with RAM, we decided that new behavioural notation must have the following
properties / support the following features:
1. Expressiveness: In RAM, the structural view presents the classes together with the operations they offer, and the message views present the
interaction between objects when one of the public operations is invoked.
This does not convey complete information on the order in which operations can be invoked on object instances. The notation we are looking for
should support the specification of such invocation protocols.
2. Conciseness: The notation should be capable of specifying invocation
protocols of class instances in a straightforward and concise way. This
requirement is important to reduce accidental complexity.
3. Diversity: The notation should not be similar to sequence diagrams.
This will force the modeller to look at the design concern from a different
point of view while specifying the protocols than during elaboration of the
behaviour of operations.
4. Modularity: Since RAM focuses on the modular representation of design
concerns for the purpose of creating an independent module that can be
developed in isolation from the other software components, the modelling
notation must support the declaration of independent modules as well.
5. Composition: Since a modeller can elaborate a complex design concern
by composing multiple RAM models, the modelling notation for state
views must support composition as well. Whether A extends B or whether
A customizes B, the protocols for object instances can change. The composition operator(s) of the notation must therefore support:
(a) Adding New Operations: Both the model user and the model
incrementer might define new operations, which need to be integrated
by composition with the protocol of B. In case of customization, the
public protocol of B needs to be integrated with the complete protocol
of A. In the case of model incrementing, the complete protocol of B
needs to be integrated with the complete protocol of A.
(b) Adding Constraints: Both the model user and the model incrementer might need to define additional constraints on the protocol
of B. It should therefore be possible to restrict the public or the
complete protocol of B, respectively.
28
(c) Coupling Protocols: A RAM model can depends on multiple other
aspect models. For example, A can extend B and customize C. In
that case, it should be possible for the model designer of A to specify
a coupling between the protocols of B and C in the case where classes
from B and C are mapped to the same class in A.
6. Verification: The state view notation should be appropriate for:
(a) Verifying Internal Consistency: It should be possible to verify that a model designer is specifying the behaviour provided by the
model in a consistent way, i.e., that there is no contradiction between
the specified object invocation protocols and the interactions between
objects specified in the message views.
(b) Verifying Usage Consistency: It should be possible to verify that
a model user is calling the public operations provided by the RAM
model in the right order. In other words, the notation should support
the definition of a public protocol.
(c) Verifying Increment Consistency: It should be possible to verify
that a model incrementer is calling the operations provided by the
RAM model in the right order. In other words, the notation should
support the definition of a complete protocol.
(d) Verifying Composition Consistency: For woven models consisting of many interdependent RAM models it should be possible to
verify that all scenarios specified within the woven message views are
acceptable operations according to the combined protocol specifications of each model.
4
Related Work
Historically, protocols have been defined using state-based notations, such as,
finite automata, because these notations are effective to capture software systems behaviour. State diagrams are also significantly different from sequence
diagrams, which satisfies requirement 3. We therefore investigated several statebased aspect-oriented approaches, including HiLa [33] and the framework designed by Elrad et al. [12]. In this section we describe some approaches that
applied aspect-oriented modelling techniques in the context of state transition
modelling.
4.1
UML
The UML Superstructure document v.2.1 and v2.2 [19] describes several concepts for specifying, visualizing, constructing and documenting the function,
architecture, and design of object-oriented systems. This modelling language
provides different views to capture the static and dynamic behaviour of a software system. UML class diagram are used to model and describe the structural
29
view of objects. This view is complemented by a state transition modelling artifact, state machines, inspired from David Harel’s statecharts, to describe the
dynamic behaviour of the object. A statechart is an efficient modelling concept
when the modelled behaviour of an object depends not only on a given input
but also on the current state of that object.
UML defines a State Machine Package where two kinds of state machines
were described to model discrete behaviour through finite state/transition systems: behaviour State Machines and Protocol State Machines.
• Behaviour State Machines (BSM): This type of state machines are
used to specify discrete behaviour of a part of a designed system, e.g.,
class instances, through finite state transitions. A state machine usually
presents the behaviour of one “behavioured classifier” which is called its
context. The latter defines which attributes and operations are defined
for this state machine.
• Protocol State Machine (PSM): is a specialization of Behaviour State
Machine. It expresses the usage protocol or lifecycle of a classier. It
specifies the allowed call sequences on the classifier’s operations.
An example of a UML behavioural state machine is shown in Fig. 8 where we
pointed out the different elements of the BSM that we are describing in this
section.
State
Drink Machine
display amount entered
Start State
Idle
display amount entered
Display goodbye
Final State
Orthogonal
regions
Transition
Idle
{
choices
displayed
Event
Guard
Action
Propagated event
Amount
displayed
display choices
deposit coin
[deposited funds < drink cost]
/hold coin in temp bin
^display amount entered
deposit coin /hold coin in temp bin
pull return coin lever
/ return funds
pull return coin lever
/ return funds
Waiting for funds
Do /
CalculateFundsSum
deposit coin
[deposited funds >= drink cost]
/hold coin in temp bin
^display choices
Waiting for selection
change returned /
^display goodbye
select drink /dispense drink
dispensed
Refunding change
Dispensing
Figure 8: An example of UML Behavioural State Machine.
30
State machines can be composed of more than one region i.e. orthogonal
regions. The life cycle of an object is split into different states. A state machine
should have one initial state, i.e., a special state that is the source for a single
transition to the default state of the object. The transition from one state to
another is triggered by the occurrence of an event.
In a state machine, an individual state of an object is graphically represented
by a rounded rectangle node in a graph. A state has different compartments: the
name, the internal activities and the internal transitions compartment. A state
can be anonymous, i.e. without name. For this reason the name compartment
in UML can be empty. The second compartment holds a list of internal actions
or state activities (do activity) that are performed while the classifier is in
the state. In Fig. 8, Waiting for funds state has an internal activity “do”
state. There are three reserved labels for activities: entry, exit and do. Entry
behaviour is executed whenever a state is entered and conversely, exit behaviour
is executed prior to leaving the state. The label do refers to an ongoing event
that is performed as long as the modelled element is in the state or until the
computation specified by the expression is completed. In the drink machine
example (Fig. 8) all the states of the state machine are simple states. However,
UML defines three kinds of states: simple (with no regions), composed ( has
only one region) and orthogonal (with multiple regions).
Events are represented by one or more transition arcs interconnecting the
state nodes. A transition allows the transition of a state machine from a state
configuration to another upon the occurrence of an event. It is graphically
represented by a directed arc linking a source state and a target state.
In BSM, a transition has a label describing the event in the following way:
event[guard]/action
where event is the name of the event that triggers the transition, guard
is an optional condition that can be evaluated to true or false, action is an
optional behaviour resulting from the firing of the transition. Action can be
simple program statements, such as “a++” or calls to operation defined within
the object. Transitions can have also propagation events, generated after the
transition is taken, which are specified next to actions and preceded by a carat
(^).
In the case of PSM, a transition specifies a legal transition for an operation
and it has the following label:
[pre-condition]event/[post-condition]
where the pre-condition is similar to the guard in BSM. Fig. 9 shows the
protocol state machine of a drink machine classifier. Since a PSM is defined
in the context of a classifier, the different elements of the transition (pre, postcondition and event) can be defined using the operations and attributes of the
classifier as it is shown in Fig. 9.
There are two main differences that exist for the definition of a state in
protocol state machines, versus a state in behavioural state machines. The first
31
Drink Machine
displayMessage
create
NoMessageDisplayed
displayMessage
MessageDisplayed
ShutDown
Transition
create
{
Idle
shutDown
Pre-condition
Event
Post-condition
[deposited_funds < drink_cost]
depositCoins
/[deposited_funds < drink_cost]
depositCoins
Waiting for funds
[returnCoinLeverPulled()]returnFunds
[deposited_funds < drink_cost]
depositCoins
/[deposited_funds >= drink_cost]
operation
attribute
Waiting for selection
[returnCoinLeverPulled()]returnFunds
returnChange
Refunding change
dispenseDrink
selectDrink
Dispensing
Figure 9: An example of UML Protocol State Machine.
is that several features in BSM do not exist for PSM, such as entry, exit and do
state behaviours. The second is that states in PSM can have invariants, which
are represented by a textual expression placed after/under the name of the state
and surrounded by square brackets.
An event detected by a state machine may result in one or more transition
being enabled for firing. If the event is not allowed in the current state configuration it will be discarded. If an event enables more than one transition in
different orthogonal regions, it is possible to fire them all, i.e., one transition
per orthogonal region.
In UML, a state machine can be extended, i.e., regions, vertices and transitions can be added and redefined. A simple state can be redefined to a composite
state and a composite state can be extended by extending its regions or adding
new ones. State machine extension was introduced following the example of
class specialization.
4.2
Mahoney et al.
The approach by Mahoney et al. [11] extend Harell’s statecharts to create
reusable orthogonal abstract statecharts. They present a methodology that
uses UML semantics without adding any major extension. Such an approach
has the benefit of allowing the use of existing CASE tools.
The idea is to create semi-independent statecharts that communicate through
32
broadcasting events to orthogonal regions. Both core and aspect concerns are
defined by static classes and each class has a statechart attached to it that describes its dynamic behaviour. Associations define the communication between
the core and the aspect classes, and specify the temporal order in which the statecharts handle events. Weaving the core and the aspect concerns together to get
one executable module is implicitly done by placing each semi-independent statechart of the concerns in question in an orthogonal region of a statechart. The
authors have defined design guidelines that, when followed, enable traceability
of crosscutting requirements from the design to code.
This approach has the following benefits: (1) implicit weaving as described
earlier is done using the orthogonality of the statecharts and event propagation in a straight forward way, (2) adaptability, i.e., extending the model by
adding aspects orthogonally, is done without impacting any of the other orthogonal regions, and (3) traceability, i.e., the ability to trace crosscutting concerns
requirements from the design to code.
The main drawback of the approach that was noticed by the authors [12]
was the tight coupling between the core and the aspect statechart due to the
explicit event propagation performed by the developer. To avoid such coupling,
the authors introduced the concept of event reinterpretation, i.e., high level
declarations allowing an event in one statechart to be treated as a completely
different event in another statechart.
A Java framework was implemented as a proof of concept that permits the
translation of a statechart design into a skeleton code for a class. However, the
authors do not provide an integrated and concrete model view where aspects
would already be woven into base classes.
4.3
The Motorola Weavr Approach of Cottenier et al.
Cottenier et al. created the Motorola WEAVR [10], a tool developed and used
in an industrial setting. It focuses on MDE with aspect-orientation using an
aspect-oriented modelling engine for UML 2.0 state diagrams. WEAVR is an
add-in for the Telelogic TAU tool. Detailed models with regard to code generation are described using composite-structure architecture diagrams — defining a hierarchical decomposition of a system — and transition-oriented state
diagrams — defining detailed behaviour. An action language is used for the
complete implementation at the model level. A profile for UML 2.0 is used to
define aspect models which crosscut certain classes. The designer is supported
by a join point visualization engine to visualize and simulate effects of an aspect
on a model. Pointcut and advice are expressed by state diagrams. The weaving
is then performed right before the code generation.
4.4
HILA
Zhang et al. propose the High-Level Aspects for UML State Machines (HiLA)
approach [33], in which they significantly extend UML state machines with
aspect-oriented modelling techniques. HiLA was designed to be applicable to
33
parallel and hierarchical UML state machines, where in general concurrency
increases the difficulty of correct and modular modelling. The authors had
identified three major weaknesses with UML state machines: (1) Individual
features can not be modelled separately, (2) the level of abstraction is too low
and (3) features which concern the interaction between different state machines
are modelled by showing the effect on a single state machine only.
HILA uses state machines to specify behaviour of base machines and aspect
machines, which can be parameterized by means of UML template parameters.
They provide several asymmetric pointcut-advice composition mechanisms that
enable aspects to disallow and restrict transitions, describe mutual exclusion between two states in orthogonal regions and coordinate multiple state machines.
This approach, while powerful for specifying detailed behavioural designs, has
the drawback of the complex composition semantics of the different composition
operators.
4.5
Protocol Modelling
Protocol Modelling approach (PM) [24] was specifically designed for modelling
protocols, and comes with a formally defined composition operator. The authors
work progressed from developing a scheme for generating code from models to
developing a behavioural modelling approach.
The PM approach is based on the concept of a “Protocol Machine”, a reusable
behavioural component of the model that can either ignore, accept or refuse
events that are presented to it. A protocol machine is represented using a
state transition diagram. Its aim is to define an allowable sequence of event
invocations in the life of an object. This goal is similar to the one defined for
the protocol state machine in UML, described in section 4.1, with the exception
that PSM handle operations rather than events.
A state protocol has a repertoire of events that it understands. An event
can be ignored by a protocol machine if it is not represented in this machine’s
repertoire. If the event belongs to the state protocol’s repertoire, it will be
accepted only if it can be processed in the current state, i.e., it is an allowable
event invocation in the current state, otherwise it will be refused.
The PM approach is modular: a protocol model of a system is composed of
a set of protocol machines and each machine describes a partial behaviour. PM
supports a highly compositional style of modelling. The partial behaviours are
composed together to create the behaviour of the full system using a parallel
composition operator (P || Q) as defined by Hoare [21]. CSP composition has
the advantage of being a well defined and understood concept, and it enables the
modeller to perform local reasoning on models while giving him the ability to
deduce the properties of the whole system from the knowledge of the behaviour
of the composed protocols [25].
Applying CSP composition to protocol machines results in a composed state
protocol that can accept, ignore and refuse events depending on the behaviour of
the composed machines. It ignores an event if both composed machines ignore
this event. If either machine refuses the event, the composed machine will refuse
34
balance +=
Deposit.amount
balance = 0
Open
Withdraw
Deposit
Active
Close
Closed
Open
Freeze
UnFrozen
Withdraw
balance -=
Withdraw.amount
Frozen
Release
Machine 2
Machine 1
State Function:
if( balance < 0) return "Overdrawn"
Else return "In Credit"
State Function:
if( balance < -50) return "Over Limit"
Else return "Within Limit"
Withdraw
Release
In
Credit
Within
Limit
Close
Machine 3
Machine 4
Figure 10: Bank account example modelled using Protocol Modelling
it. Otherwise the event is accepted. Despite the fact that a protocol machine
has the same state transition notation as UML state machines, their semantics
are different since the UML state machine doesn’t have the semantics for event
refusal.
In protocol modelling there are two kinds of states: stored state and derived
state. A state protocol can be composed of only one kind. A stored state is a
standard state where updates to the state are defined implicitly by the statetransition topology. A derived state is a special state introduced to increase the
expressive power for describing action sequencing protocol. When using this
kind of state in a protocol machine, the state can be derived on the fly rather
than being stored as part of the machine’s local storage.
From a graphical representation, a derived state is represented by a circle
with a double border. Besides, such a state doesn’t need to be topologically
connected since the new state that results from a transition firing is not determined as the end point of a transition. Moreover, a protocol machine with a
derived state doesn’t have a start state as it is the case for the standard protocol
machine.
Fig. 10 shows an example of a simple bank account[24] modelled using PM.
The example was modelled using four protocol machines: two machines using
stored states (machine 1 and 2) and two machine using derived states (machine
3 and 4).
A derived state constraint can be applied on the current state (machine 4)
or on the resulting state (machine 3). In machine 4 the derived state acts as
a guard, i.e., Release and Close transitions can be fired only if the balance is
positive. In machine 3 the derived state is used to specify that a Withdraw event
should not be accepted on a bank account object if it would lead to a negative
35
balance.
Applying the CSP composition to these four machines yield the complete
behaviour of the account bank. Here are two scenarios that illustrate how an
event can be refused by the composed protocol machine:
1. The protocol machine is in the (Active, Frozen) state configuration and
the balance is superior to 100, a Withdraw event with an amount of 50
when received by the protocol machine will be refused because it will be
refused by machine 2. Machine 2 has the event Withdraw in its alphabet
however being in the state Frozen this event can’t be processed. For the
other machines, Withdraw is accepted by machine 1 and machine 3 and
ignored by machine 4.
2. The protocol machine is in the (Active, UnFrozen) state configuration
and the balance equals -50, when a Close event is received by the protocol
machine, the state Overdrawn is calculated on the fly and the machine 4
will refuse the event since the bank account is not in the In Credit state
and as a result Close will be refused by the composed protocol machine.
An important property of PM is that the execution semantics are deterministic.
In other words, repeated executions of a protocol model always yield the same
result. If a given sequence of events is presented to a model twice starting from
the same initial state, the final state of the model will be the same, as will be
the set of events that it could accept next. This is not the case for UML state
diagrams, for instance, which includes non-determinism among orthogonal composite states. Determinism is required for unambigous specification of protocols
and reasoning about behaviour traces.
5
Specifying RAM state view with PM
After studying the different approaches described in section 4, we ended up using
Protocol Modelling (PM). The PM approach is designed specifically to specify
invocation protocols, and by associating a protocol machine with each class in a
RAM model we are able to satisfy our first requirement as defined in section 3.
Moreover, protocol machines have the property that large, complex machines
can be assembled from small, simple ones allowing to describe the behaviour of
a complex system using simple protocol machines describing partial behaviours.
This criteria allows us to fulfill requirement number 4.
In order to define a complete notation that fulfils our requirements and
provides the level of detail that is necessary for state views, an analysis of the
different features of PM and how they are best used in the context of RAM was
performed.
5.1
General Overview
State views in RAM are tied to an aspect and specify the behavioural contract,
i.e., the protocol, of instances of classes defined in the structural view. Hence,
36
a RAM model can have more than one state view. For each classifier figuring
in the structural view a state view has to be provided. A state view assembles
one or many protocol machines, each describing a partial behaviour of the class.
The protocol machines are composed together, following the PM approach, using
the CSP composition to create the complete picture of the class; behavioural
contract. Inside the state view, the protocol is defined for the operations of
the owner classifier. This includes operations and classes that become available
through mappings when instantiating other aspects.
state view |Data
add
add
Empty
NotEmpty
|Data
remove
[size == 0]
getAssociated
|Data
contains
Accessible
getSize
get
Figure 11: ZeroToMany State View for |Data
Fig. 11 shows how we used PM to describe the state view of the |Data class
of the ZeroToMany-Ordered RAM model shown in Fig. 1. The state view of
|Data has two state machines i.e., protocol machines. The first one is describing
the fact that calling an add operation changes the state of a |Data object from
Empty to NotEmpty, and that remove operations should only be called after
at least one add was invoked. Also, when removing the last |Associated object from the sequence of objects, the state of the |Data instance changes back
to Empty, thus disallowing the invocation of remove operation. The second
protocol machine describes the protocol for the getter and query operations.
Since they do not alter the state of the object when called, there are no restrictions specified on their protocol. This is a great example on how PM supports
conciseness (requirement 2). Each state machine is simple: it only focusses on
operation invocations and how they alter the object’s logical state. To obtain
the complete protocol for |Data instances, the modeller can apply the CSP operator mentally on the two state machines, which yields the composed protocol
machine shown in Fig. 12. Notice that the state view with two state machines,
even for a simple class such as |Data, is easier to understand than the more
cumbersome composed state view.
37
aspect Tracing extends ExecutionContext depends on Traceable, ZeroToMany-Ordered
structural view
Context
Trace
|Participant
~ Context Context()
+ boolean wasAccessed(|Traced)
+ boolean wasModified(|Traced)
+ Set<|Traced> getAccessed()
+ List<Trace> getTraces()
+ removeTraces(Set<|Traced>)
+ addTrace(Trace trace)
+ removeTrace(Trace trace)
+ getNbTraces()
+ |Participant getCurrent()
+ Context getContext()
+ createAndEnterContext()
+ leaveContext()
|Participant
|Traced
|tracedMethod<AccessKind>
<<enumeration>>
AccessKind
Read
Write
Update
|Traced
+ * |tracedMethod<AccessKind>(..)
Instantiations:
ExecutionContext:
Traceable:
|Participant → |Participant; Context → Context
|Traceable → |Traced; |traceableMethod → |tracedMethod; Trace → Trace; AccessKind →
AccessKind
ZeroToMany-Ordered: |Data → Context; |Associated → Trace; getAssociated → getTraces; add → addTrace; remove
→removeTrace; getSize → getNbTraces
Figure 13: Structural View of the Tracing RAM Model
state view IData
getAssociated contains
|Data
Empty
get
getSize
getAssociated contains
add
[size == 0]
add
NotEmpty
remove
get getSize
Figure 12: Composed State View of |Data
5.2
Using RAM State Views
This section illustrates by means of a more complex example how we intend
the new state views to be used when modelling with RAM. The example design
concern that we are going to model is Tracing.
Tracing The main idea of Tra cing is that it allows instances of the class
|Participant to enter what is called a Context – an abstraction of an
area of computation. Once inside a context, all subsequent operation invocations on instances of the class |Traced are recorded with the context,
until the participant leaves the context again. Such a design concern can
be useful for debugging or logging purposes.
Fig. 13 shows the structural view of the Tracing model. Tracing depends
on several other models to implement its behaviour as it is shown in Fig. 14.
First, it is an extension of the ExecutionContext model, which already defines
the classes Context and |Participant together with the behaviour that allows a participant to enter and leave a context (see ExecutionContext model
description below). Tracing also depends on Traceable (see Fig. 4 ) to provide the behaviour of creating a trace for a method invocation, and finally on
ZeroToMany-Ordered (see Fig. 1) to associate a list of traces with the context.
38
Tracing
Traceable
ZeroToMany-Ordered
ExecutionContext
Figure 14: Tracing Dependencies
aspect ExecutionContext
|Participant
structural view
|Participant
Context
~ Context Context()
~ addParticipant(|Participant)
~ removeParticipant(|Participant)
~ contextCompleted()
0..1
myContext
0..1
myParticipant
+ |Participant getCurrent()
+ createAndEnterContext()
+ Context getContext()
- setContext(Context c)
+ enterContext(Context c)
+ leaveContext()
state view Context
Context
Idle
contextCompleted
addParticipant
removeParticipant
Active
Completed
Figure 15: ExecutionContext Model
ExecutionContext Fig. 15 defines the ExecutionContext model that describes
an area of computation. ExecutionContexts structure the execution of
an application. They give identity to the set of operations executed by
threads on objects over a given period of time in the pursuit of a goal.
A transaction is an example of a context that exhibits additional properties, i.e., the Atomicity, Consistency, Isolation and Durability (ACID)
properties [18].
In subsection 3 we listed several consistency verifications that we would like
to be able to conduct using our new state views. The following subsections
describe how some of them can be realized.
5.2.1
State Views for Public Operations
One requirement was verifying usage consistency (requirement 6b), which indicates that it should be possible to use the state view to ensure that when a
model user 1 invokes the behaviour of a classifier in a message view, the invocation order of this classifier’s operations is respected. A model user can only call
public operations of the model he is customizing, thus it is sufficient to define a
state view that only specifies the protocol for the public operations.
For instance, Tracing customizes the ZeroToMany-Ordered model to enable
a Context instance to store a list of Traces. In this case the model designer of
1 See
subsection 2.2 for the definition of the different kinds of users.
39
Tracing (which is a model user of ZeroToMany-Ordered ) needs to understand
the public behaviour of the |Data class to be able to use it correctly. After creating the message views of the Context class, the modeller (or the modelling tool
he is using) can verify for each operation that the invocation of the operations
belonging to |Data respects the public protocol as specified in Fig. 11.
As a simple example, let’s take the case of the message view of the operation
removeTraces shown in Fig. 16. This operation, given a set of Traced objects,
removes all the traces that belongs to these objects from the context. Operations
used by this message view, getTraces and removeTrace, are added to Context
after using the class |Data, i.e., getTraces is getAssociated and removeTrace
is remove as mentioned in the instantiations section of the structural view of
Tracing (see instantiation compartment in Fig. 13). Since there is no restriction
for calling getAssociated before remove according to the public state view of
ZeroToMany-Ordered ( Fig. 11), the message view of removeTraces is using the
operations of |Data class correctly.
message view removeTraces
target: Context
removeTraces(t)
traces := getTraces()
loop [tr within traces]
tr: Trace
target := getTarget()
t: Set<|Traced>
remove := contains(target)
opt [remove]
removeTrace(tr)
Figure 16: removeTraces Message View
Applying the same idea to the next level, the model designer of Tracing
should specify a public state view for Tracing, so that the model users of
Tracing can verify that he is using Tracing correctly. To model the public
state view of the class Context, a model designer needs to consider the public
operations of this class and determine for each operation the possible constraints
for calling it. In our case, the major constraint for Context is that the operation
removeTraces can not be called unless a trace was added previously through
addTrace (notice that the constraint that “removeTrace should only be called
after at least one addTrace was invoked” is already described in the state view
of |Data (see Fig. 11)). Fig. 17 describes a public state view for Context that
expresses this constraint.
5.2.2
Internal State Views
To be able to do a similar verification for model increments, a more elaborate
“internal” state view needs to be defined that describes the invocation protocol
detailing not only the public, but also the internal operation invocations that
40
[size == 0]
Context
NoTraces
addTrace
TraceAvailable
removeTraces
addTrace
wasAccessed Context
getTraces Available
getAccessed getNbTraces wasModified
Figure 17: Public State View of Context in Tracing
addParticipant
Context
Idle
addTrace
Active
removeParticipant
Figure 18: Internal State View of Context in Tracing
are acceptable during the life time of an object. This internal state view should
describe how non-public operation invocations relate to public ones and to each
other. This makes it possible to verify increment consistency and composition
consistency (requirement 6c and 6d).
For example, Fig. 15 shows the structural view of the ExecutionContext
model together with the state view of the class Context. The state view defined
for Context in ExecutionContext is an internal state view, since this class does
not have any public operations. Since Tracing extends ExecutionContext, the
Context class in Tracing is mapped to the Context class in ExecutionContext.
The model designer of Tracing should hence specify any protocol restrictions
that should be defined between the operations added to Context by Tracing
and the operations that come from ExecutionContext.
One constraint that a Context object in Tracing must not violate is the
fact that the operation addTrace should only be called when the context is in
the state Active, i.e., after addParticipant is called. Fig. 18 shows the state
machine that expresses such a behavioural constraint.
Composing the public and the internal state views using CSP composition
results in the state view shown in Fig. 19. The composed view can subsequently
be used to verify the consistency of message views that were specified in models
that customize or extend Tracing2 .
2 For simplicity and readability reasons, the state machine with the getters and query
operations from ZeroToMany-Ordered were not added to Fig. 19. To create the actual woven
model it suffices to add to each of the depicted states all self transitions of the state Available
from the state view in ZeroToMany-Ordered.
41
state view Context
Context
contextCompleted
Completed_NoTraces
addParticipant
Idle_NoTraces
Active_NoTraces
removeParticipant
[size == 0]
[size == 0]
[size == 0]
addTrace
addTrace
contextCompleted
Completed_TracesAvailable
Idle_TraceAvailable
addParticipant
Active_TraceAvailable
removeParticipant
removeTraces
removeTrace
removeTraces removeTrace
removeTraces
removeTrace
Figure 19: Composed State View of the Class Context in Tracing
5.3
Discussion
This section discusses how the simplified version of PM that we integrated into
RAM satisfies the requirements we detailed in subsection 3.
Expressiveness and Diversity: State views add additional behavioural
constraint specifications to a RAM model. The structural view specifies the
types of objects a concern defines and what functionalities they offer. The
message views show how these objects interact with each other and with the
objects of other concerns to achieve this functionality. They also show for
these scenarios in what sequence the operations of an object are called. For
example, the removeTraces message view (Fig. 16) presents an overview of
the interactions between Context, Trace and Set<|Traced> objects when the
removeTraces(Set<|Traced> t) operation is called, and shows the scenario
where getTraces() is called before removeTrace(Trace tr). The state view
of Context (Fig. 17 and 18) complements these views by giving information
about how individual objects can be used, i.e., the order in which an object’s
operations should be called, from a state perspective. For example, the fact that
addTrace should be called after addParticipant is invoked is clearly expressed
as a constraint in the Context state view (Fig. 18). We have so far not encountered a situation in which it was not possible to express a protocol using our
new state views.
Conciseness: The protocol of the objects can be concisely described using
public and private state views. Woven state views that combine the protocol of
several models can be generated on demand. To further increase conciseness,
we made it optional to specify a protocol for operations that have no effect on
the conceptual state of an object. In other words, if no transition is defined for
an operation we assume that there is no restriction on its use.
Finally, we added generic events to increase conciseness of state views,
which can be used to group operations when operations affect the state of an
object in the same way. For example, the getters and query operations in
Context can be replaced by one event that can be called getters_queries as
follows: getters_queries = {wasAccessed OR getAccessed OR getTraces
OR wasModified OR getNbTraces }. As a result, only one transition needs
to be shown in the state view, where otherwise five transitions with the same
42
source and target states would have been shown.
Modularity: CSP || composition allows the modeller to model the state
views for each class of a concern independently, and compose them together to
form the complete description of the protocol of a class. Using instantiation
directives to map model operations from one model to another model makes
reuse possible. For example, the Tracing concern was modelled separately of
the ZeroToMany-Ordered concern, i.e., the protocols for Context and |Data are
specified separately. Modularity can even be exploited within a RAM model,
since the model designer can specify the protocol of a class using multiple state
machines if he judges that using one state machine will be too complicated
or cumbersome. For example, the getters and query operations of the class
Context in Tracing were modelled in a separate state machine in the public
state view to increase readability (see Fig. 17).
Composition: The CSP operator offers a straightforward way to support
adding of new operations, adding of constraints and coupling of protocols.
• Adding new operations: This kind of transformation is easily expressed
by adding a new state machine that integrates the new operation into the
existing protocol. For example, Tracing Context is using the operations
of ZeroToMany-Ordered |Data to manage the list of Trace s, and additionally defines a new operation removeTraces. This operation affects
the conceptual state of |Data , and therefore needs to be integrated in the
protocol defined for |Data . For this reason, a state machine was defined
(Fig. 17 ) to clarify the relationship between the behaviour of |Data and
the new added operation. Other operations were added, i.e., wasAccessed,
wasModified and getAccessed, but since they do not affect the state of
a |Data object they were added to the queries state machine. Notice that
Context of Tracing is extending the behaviour of Context coming from
ExecutionContext by adding all the operations coming from |Data and
all the newly defined operations. To determine the complete protocol of
the new, composed Context object, the state views of the three classes i.e.
ExecutionContext Context, Tracing Context and ZeroToMany-Ordered
|Data are composed.
• Adding constraints: CSP composition works by synchronizing state machines on events that are common in the alphabets of these entities. Regulation of the behaviour of an object by restricting operations is possible due
to the ability of a composed state machine (M1 || M1) to refuse an event
if M1 or M2 can not process this event in the current state. For instance,
imagine that we want to change the behaviour of the object Context in
the ExecutionContext concern in such a way that once a Participant
is removed, no Participant can be added any more. In Fig. 20, the state
machine (b) was added to the original state machine of Context to reflect
this constraint. Once the Context is created and addParticipant and
removeParticipant operations are invoked, the context object will be in
the state Idle in machine (a) and ParticipantRemoved in machine (b). According to the rules of PM, it is not possible to call addParticipant again
43
a) Context original state machine
Context
Idle
contextCompleted
addParticipant
removeParticipant
Active
Completed
b) State machine adding the constraint
Context
Idle
addParticipant
ParticipantAdded
Figure 20: Adding Constraints Example
on the object. Machine (a) allows processing addParticipant, but machine (b) has the operation in its alphabet, but it does not allow processing
it in the current state (ParticipantRemoved ). As a result, addParticipant
is rejected by the composition.
• Coupling protocols: Orchestrating the behaviour of the concerns that
a model is extending and depending on is done simply by specifying
the common behaviour in a separate state machine. For example, in
Tracing, the class Context is mapped on the one hand to the class
Context in ExecutionContext and on the other hand to the class |Data
of ZeroToMany-Ordered. The behaviour of the object |Data is restricted
by the behaviour of the object Context of the ExecutionContext concern
as follows: adding traces should be done only when the Context is active,
meaning the operation addTrace (coming from add in ZeroToMany-Ordered)
should only be invoked after the invocation of addParticipant and before
that of removeParticipant. The internal state view of Context shown in
Fig. 18 presents the state machine needed to specify such an orchestration.
Sometimes orchestrating the behaviour of multiple objects can be tricky.
Fig. 21 shows an excerpt of the design of a concern called Checkpointable.
Checkpointable This concern can be used to add fault tolerance to a software application: it provides the functionality of creating snapshots of the
state of objects and restoring the states in case of a failure. The class
|Checkpointable represents the object that contains the state that needs
to be recoverable and Checkpoint is the class responsible for handling the
process.
The Checkpoint classifier needs to keep two lists of objects: the first
contains references to the original checkpointed objects and the second
contains the copies of the original objects at a specific moment of their life
cycle. Whenever an object is checkpointed, it is added to the first list and
its copy is added to the second list. Therefore, Checkpointable needs the
44
aspect Checkpointable depends on ZeroToMany-Ordered, Copyable
|Checkpointable
structural view
Checkpoint
|Checkpointable
+ Checkpoint Checkpoint()
~ Set<|Checkpointable> getCheckpointables()
+ checkpointAndAdd(|Checkpointable c)
+ restoreCheckpoint()
+ discardCheckpoint()
Instantiations:
Copyable:
|Copyable → |Checkpointable
ZeroToMany-Ordered: |Data → |Checkpoint; |Associated → |Checkpointable; getAssociated → getCheckpointables;
add → addCheckpointable; get → getCheckpointable; remove → removeCheckpointable;
contains → containsCheckpointable; size → nbCheckpointables
ZeroToMany-Ordered: |Data → |Checkpoint; |Associated → |Checkpointable; getAssociated → getBackupCopies;
add → addBackupCopy; get → getBackupCopy; remove → removeBackupCopy ; contains →
containsBackupCopy; size → nbBackupCopies
state view Checkpoint
restoreCheckpoint
checkpointAndAdd
CheckpointExist
Empty
Checkpoint
checkpointAndAdd
discardCheckpoint
restoreCheckpoint
checkpointAndAdd
Checkpoint
discardCheckpoint
A1
addCheckpointable
Checkpoint
Accessible
A2
addBackupCopy
removeBackupCopy
gettersQueries
removeCheckpointable
A3
checkpointAndAdd = {addCheckpointable And addBackupCopy}
discardCheckpoint = {removeCheckpoint[sizeCheck==1 And removeBackupCopy[sizeBackup==1]}
gettersQueries = {getCheckpointable OR getBackupCopy OR getCheckpointables OR getBackupCopies OR
containsCheckpointable OR containsBackupCopy}
Figure 21: RAM Model of Checkpointable
45
functionality offered by ZeroToMany-Ordered to manage these lists twice,
and the protocols of the two lists need to be synchronized.
Fig. 21 shows the state view of Checkpoint. To keep the state of the
Checkpoint object consistent, the following constraint should be respected:
Adding a backup copy should always follow adding a checkpointable, and
the same goes for removing. The behaviour of the two |Data objects
needs to be orchestrated, and this is described by the bottom left state
machine. The operation checkpointAndAdd is the public operation responsible for creating the copy and adding both the object and its copy
to the lists. Calling this operation includes calling addCheckpointable
and addBackupCopy3 , which means that both removeCheckpointable and
removeBackupCopy can be called at this point according to the state view
of |Data . However, there is no indication that checkpointAndAdd and the
add operations are related. Therefor the following sequence (Checkpoint,
addCheckpointable , addBackupCopy, discardCheckpoint) is not permitted by the complete behaviour of Checkpoint, which is not right. Let’s
imagine that a model designer wants to extend Checkpointable and wants
to create a new method checkpointUsingAnExistingBackupCopy that
accepts a backup copy as a parameter unlike checkpoinAndAdd. The latter method uses the functionalities provided by another aspect, Copyable,
to create a copy of the checkpointable object. A constraint cannot be removed so as long as checkpoinAndAdd is not called, discardCheckpoint
cannot be called.
To overcome this issue, an event behavioural equivalence was defined (as
shown in the last compartment of Fig. 21). This equivalence shows that
invoking the checkpointAndAdd operation affects the state of Checkpoint
the same way as calling addCheckpointable and addBackupCopy consecutively. As a result, the previously rejected sequence of operations is now
allowed by the composed behaviour of Checkpoint.
Verification: Section 5.2 discussed in details how the RAM state views can
be used to verify internal consistency, usage consistency, increment consistency
and composition consistency.
5.4
Differences between PM and RAM state views
PM is a powerful technique that was designed for a slightly different purpose.
While our requirements are clearly focussed on verification, the goals of PM
include system interaction modelling, protocol execution simulation, test- and
code generation. For that reason we decided to adapt the main ideas of PM
within RAM, but to remove some of the advanced features that we do not seem
to need for now. In summary, the differences between the original PM approach
and how we are currently using it in RAM are:
3 addCheckpointable and addBackupCopy are the same operation add of |Data class as it is
shown in the instantiation compartment of the Fig. 21
46
• While PM models specify any general event interchange, we only focus on
modelling operation invocations of design classes.
• PM focusses on modelling interactions with a system, and therefore presents
all the state machines of a system together. Consequently, all events are
global (to the system being modelled), so they need to have unique names.
To obtain the complete interaction protocol of the system, all state machines are composed with each other. In the case of a RAM model, only
state machines that are contained in the same state view are related to
each other (and logically composed with each other). Additional state view
relationships are created when classes from different aspects are mapped
together, which results in a logical composition of all the state machines
that the respective views contain. Because of that, the events in RAM
are not global to the whole system; they only need to be unique within
state views that are related to each other by instantiation mappings. For
example, the state view of |Data in Fig. 11 is composed of two state machines separated by a dashed line. These state machines are related to
each other since they are in the same state view and CSP composition is
logically applied to them. Conversely, the state machines of the state view
|Data and those of Sequence (not shown in this thesis) are independent,
since they describe the behaviour of objects that are instances of different
classes.
• PM introduces a new type of state – the derived state – which replaces
transition guards. The main advantage of derived states is that they can
be reused by different state machines, unlike guards, which are attached
to transitions. Also, derived states offer the possibility to disallow events
that could lead the system into an undesired state as it is the case of the
machine 3 in Fig. 10. So far we did not need such expressive power in our
case studies with RAM.
• Event abstraction in PM is realized by using special events called generic
events. This kind of event is used to abstract away the difference between
events that have the same effect to enable reuse of existing protocol machines in different contexts [26]. In the case of RAM, a similar kind of
protocol reuse is achieved when renaming an operation in an instantiation
directive.
47
Part IV
Metamodel for State Views
A model is an abstraction of phenomena in the real world. Its main purpose is
to support planning and early validation to partially evaluate a system before
it is realized. A model’s properties, features, graphical syntax and semantics
are defined and described using a metamodel. A metamodel is yet another
abstraction that can be seen as a special kind of model that specifies the abstract
syntax of a modelling language, and it can be understood as the representation
of the class of all models expressed in that language. Metamodels in the context
of MDA are expressed using the Meta-Object Facility (MOF), which is a OMG
standard used to define the UML.
Considering the adaptation of the UML metamodel or a subset of it to the
RAM metamodel or trying to keep the divergence as minimum as possible will
simplify the process of importing existing UML models to be used with the
RAM tool. Thus, users that designed their models in UML tools before will
be able to reuse them. Only missing information or restructuring would then
be necessary to get them compatible with RAM. This could lead to a faster
adoption by users.
The structural view and message view in RAM are based on class diagrams and sequence diagrams as defined by the Unified Modelling Language
(UML) [27]. The metamodel for these two RAM views is however considerably
simplified compared to the UML metamodel. Following the same idea and since
we have a clear idea about the different features that we want to be included
in the RAM state view, we looked at the UML metamodel for state-transition
diagrams and how it is integrated with UML class and sequence diagrams.
6
Overview of UML State Machine Metamodel
In order to be able to compare state machine diagrams and state views and
understand their differences we will take a look at the meta-model of UML
State Machine Diagrams [19] defined by the Object Management Group (OMG).
In section 4.1 we gave an overview of the different features that a UML state
machine provides and Fig. 8 shows the graphical representation of these features
using a drink machine example. The state machine package as mentioned before
has two different kinds of state machines: Behavioural State Machines (BSM)
and Protocol State Machines (PSM). Since PSM is a specialization of BSM, the
metamodel of PSM is based on the one defined for BSM with minor differences.
An excerpt of the UML metamodel for the behavioural state machine is depicted
in Fig. 22.
48
extended
StateMachine
0..*
StateMachine
region
region
0..*
1..*
region
0..*
Classifier
Region
0..1 extended
Region
NamedElement
0..* subvertex
Vertex
transition 0..*
source
1
1 target
outgoings
0..*
0..* transition
Transition
redifined
0..1 Transition
incomings 0..*
guard 0..1
exit
0..1
entry
0..1
Behavior
effect
0..1
doActivity
redifined 0..1
State
State
- isComposite: Boolean
- isOrthogonal: Boolean
- isSimple: Boolean
- isSubmachine: Boolean
0..1
stateInvariant
0..1
constraint
0..* trigger
deferrableTrigger
0..*
Trigger
state 0..*
FinalState
Figure 22: The core of the UML Behavioural State Machine meta-model
A StateMachine is the encapsulating unit of behaviour representing a behavioural state machine diagram. It can be composed of one or more Regions,
which in turn own vertices and transitions. A Classifier, on the one hand,
defines signal and call triggers that are defined for the state machine (which explains the association between Transition and Classifier in the metamodel).
On the other hand, it defines attributes and operations that are available in activities of the state machine (association between Classifier and State).
The self associations that appear on the StateMachine, Region, State and
Transition elements of the metamodel reflect the fact that a state machine is
generalizable. In this context, a specialized state machine can extend a general
one by redefining its regions, states and transitions or adding new entities.
A State is a specialized Vertex which can be simple, composite (composite
orthogonal) or submachine. As mentioned before in section 4.1 a State has three
kind of optional Behaviour, which are doActivity, entry and exit. Besides,
it has a stateInvariant, which is a Constraint specifying the conditions that
are always true when the state is the current state.
A Transition is a directed relationship between a source vertex and a
target vertex. It can have many triggers, which represent events that may
fire the transition, an optional guard, which is a Constraint that has to be
evaluated to true for the transition to be fired and finally an optional effect,
49
which englobes the behaviour performed when the transition fires (action, event
propagated).
Since protocol state machines have a different aim than the one defined for
behavioural state machine, i.e., expressing the legal transitions that a classifier
can trigger, their metamodels reflect these differences. Fig. 23 shows an excerpt
of the UML metamodel for the protocol state machine diagram.
BSM::StateMachine
Port
Protocol
0..*
0..1
generalMachine
ProtocolStateMachine
Protocol
Interface
0..1
1
0..*
1 specificMachine
ProtocolConformance
conformance
0..*
interface
0..1
Classifier
BSM::Transition
Operation
referred
0..*
0..*
ProtocolTransition
0..1
preCondition
0..1
Constraint
0..1
0..1
postCondition
0..1
StateInvariant
owningState
State
0..1
Figure 23: An excerpt of the UML Protocol State Machine metamodel
A ProtocolStateMachine is a specialization of BSM::StateMachine. Advanced state machine modelling such as sub-state machines, composite states
and concurrent regions can also be used in PSM. A PSM is always defined in the
context of a Classifier. A Classifier may have several ProtocolStateMachines,
which can happen for example when a class inherits from several parent classes
having protocol state machine. An Interface does not own detailed behaviour
specifications, but it can own a Protocol state machine specifying the legal sequences of the invocation of the behavioural features described in it. Note that
the classifier context of a state machine cannot be an interface. Since PSM can
be redefined as it is the case for BSM, every rule and constraint specified for the
general protocol state machine should apply to the specific protocol and this
done using ProtocolConformance.
A ProtocolStateMachine specifies a legal invocation for an Operation. It
doesn’t have an effect action, since the effect is specified in the corresponding
operation. All operations that can generate a given change of state for a class
should be represented in the protocol state machine. PSM has a postCondition
50
property as an additional information compared to the general transition from
BSM. It represents the condition that should be obtained when the transition
is triggered.
7
Current Metamodel of RAM
Before discussing the state view metamodel, an overview of the current metamodel of RAM is presented so that the reader can understand what existing
elements the state view metamodel can reuse / reference.
7.1
Overview
The unit of modelling in RAM is an aspect. Consequently, the Aspect root
element of the metamodel contains all other elements directly or indirectly (see
Fig. 24). Generally, an aspect contains its different views. As currently only the
structural and the message view are supported, the meta-model contains only
these view. Fig. 24 depicts an overview of the current meta-model.
layout
0..1
Layout
EObject
NamedElement
- name: String
value
1
Map
EObject
structuralView
instantiations
0..*
externalAspect
1
messageViews
StructuralView
0..*
Instantiation
- type: InstantiationType
mappings
AbstractMessageView
Mapping
- getFromElement(): MappableElement
- getToElement(): MappableElement
0..*
ClassifierMapping
attributeMappings
<<enumeration>>
InstantiationType
- Depends
- Extends
LayoutElement
- x: float
- y: float
MappableElement
0..* mandatoryAspectParameters
Aspect
value
1
0..*
AttributeMapping
0..*
OperationMapping
operation
Mappings
parameterMappings
0..*
ParameterMapping
Figure 24: General Overview of the Current RAM Metamodel
An aspect is a NamedElement that has beside its StructuralView and the
MessageViews many Instantiations and a Layout.
An Instantiation describes a dependency on some other aspect (which can
either be a customization (Depends type) or an extension (Extends type)4 ), and
contains the instantiation directives (mappings). A Mapping describes which
element from the instantiated aspect is mapped to an element in the current
aspect. In RAM, classes, attributes, operations and parameters can be mapped
between two aspects. For each one of these entities a subclass of Mapping
4 See
subsection 2.2 for more details about these two types of instantiation.
51
was defined: ClassifierMapping, AttributeMapping, OperationMapping and
ParameterMapping.
Furthermore, an Aspect contains a list of its mandatory instantiation parameters. This is a derived property as it can be computed from all elements of
the structural view that are partial.
7.2
Structural View
The StructuralView represents the class diagram and its basic structure, and
its metamodel is shown in Fig. 25.
MappableElement
Operation
- abstract: boolean
- partial: boolean
- static: boolean
- visibility: Visibility
operations
<<enumeration>>
Visibility
public
private
protected
package
parameters
Parameter
0..*
0..*
returnType
1
type
Classifier
classes
0..*
0..* superTypes
1
1
Type
StructuralView
associationEnds
0..*
ImplementationClass
- instanceClassName:
String
type
Class
- partial: boolean
- abstract: boolean
NamedElement
1
type
associations
AssociationEnd
- navigable: boolean
+ getType(): Type
0..*
attributes
Association
1..*
association
1
ends
2
Attribute
Figure 25: Overview of the Structural View Metamodel of RAM
This view contains a list of Classifier and Association. Classifier is
a Type, i.e., an abstract class that has a name and contains a list of operations.
The RAM meta-model distinguishes between classes an aspect introduces and
classes that are reused from the programming language or a certain framework.
In subsection 2.1.1 we mentioned how the aspect ZeroToMany-Ordered reuses
the class java.util.Set of Java (see Fig. 1). An ImplementationClass inherits the properties of Classifier and additionally has an instance class name
stating the class name of the implementation class.
An Operation has a name, a return type, may have one or more parameters,
and is described by four properties: abstract, partial, static and visibility. A
Parameter has a type and a name.
A Class is another entity that inherits from Classifier. It has a list of
attributes, and is described by two properties: abstract and partial. The latter
indicates if this class is complete or not. A Class may have one or more super
types. Classifier, Attribute, Operation and Parameter are all specializations of MappableElement, meaning that they can be mapped when instantiating another aspect. The Class attributes are split into two kinds: Attributes
52
and AssociationEnds. This is different from the UML Class Diagram, where
a Class contains properties which refers to both. An Attribute represent a
simple property of a Class, i.e., a primitive type property. It has a name and is
typed, where the only possible types are primitive types. An AssociationEnd
belongs to an Association and has a property navigable that specifies if it is
navigable.
7.3
Message View
The MessageView contains the sequence diagrams, and an excerpt of the part
of the RAM metamodel that supports sequence diagrams is shown in Fig. 26.
The sequence diagrams used in RAM, unlike UML sequence diagrams, describe
only interchanges of messages in the form of operation calls.
An Aspect can contain more than one MessageView. The latter is specified for a specific Operation (coming from the structural view) and contains
the specification of the operation it specifies. However this is not mandatory,
because partial operations usually don’t have a specification. Interaction describes the actual behaviour in the form of operation invocations. For this
purpose it contains, besides to other entities, at least one Message. One of the
properties of a Message is its return value, and this information is represented
in the form of a ValueSpecification. The latter was inspired from the UML
ValueSpecification which is “an abstract metaclass used to identify a value or
values in a model. It may reference an instance or it may be an expression
denoting an instance or instances when evaluated” [27].
NamedElement
- name: String
Aspect
messageViews
Operation
1
specifies
0..*
MessageView
specification
0..1
Interaction
messages
1..*
Message
- selfMessage: Boolean
0..1
returns
ValueSpecification
Figure 26: An excerpt with Important Elements of a RAM Message View
8
New RAM State View Metamodel
This section presents the new RAM state view metamodel (see Fig. 27). It defines the simplified PM approach that we decided to use as described in section 5.
53
The first step was to extract the required elements from the UML metamodel
(see section 6) since the UML meta-model is very general, allowing the definition
of transitions using any kind of events, and has different capabilities then our
approach, e.g., allowing the definition of behaviours inside states and allowing
the redefinition of states, transitions, regions, etc.
Three entities from the RAM metamodel were reused in the state view metamodel: Classifier and Operation from the structural view metamodel, and
ValueSpecification from the message view metamodel.
An Aspect can now have several StateViews, a StateView for each Classifier
defined in the StructuralView. Because state views are mainly used for documentation and verification purpose, we do not make them mandatory. Hence
an aspect can have zero StateViews (which also makes the new metamodel
backward compatible with the old one). Besides, partial classes sometimes do
not have operations, thus a protocol can not be defined for them. A StateView
knows for which Classifier it specifies a protocol for, and it contains a set of
StateMachines.
A StateMachine is the entity that defines the reusable protocol component
of the model, which can be composed with other StateMachines using the CSP
|| operator. This entity is composed of a set of states, one of which is the start
state, and a set of transitions.
A State represents a logical state of the object for which we are defining the
protocol. A State has a name, a set of outgoing Transitions, i.e., allowed operation calls from this state, and a set of incoming Transitions, i.e., operation
calls that led the object to be in this State.
A Transition connects at most two states, startState designates the state
in which the object must be to accept an operation call, and endState is the
new state of the object after the call has been made. EndState and startState
can refer to the same state, since some operation calls, e.g., getters, do not alter
the state of the object. Since in RAM we are only interested in operation call
events, a Transition has a signature of type Operation, i.e., it stands for calls
to that operation only. Moreover, a Transition has at most one guard, which
is a condition that has to be evaluated to true for the protocol to accept a call
to the transition’s operation.
A guard is of type Constraint, which is a ValueSpecification, a component that was borrowed from the MessageView metamodel, which in turn was
inspired from the UML metamodel. A Constraint represents a condition or
restriction expressed in natural language text or in a machine readable language
for the purpose of declaring some of the semantics of an element.
Transition Substitution
We mentioned in section 5.3 the need for a kind of mapping between transitions
for the purpose of (1) conciseness and (2) a special case of coupling protocols.
In the first purpose, the relation between the transitions being substituted is
an OR relation meaning that the substituting transition can be triggered if
one of these transitions is triggered. However in the second kind of purpose, the
54
NamedElement
- name: String
Aspect
stateViews
owner
1
0..*
StateView
1
Classifier
specifies
statMachines
1..*
operations
StateMachine
1
signature
states 1..*
1
State
start
transitions
0..*
1
endState
Operation
1..*
Transition
incomings
outgoings 0..*
startState 1
0..*
0..1
guard
Constraint
1
specification
ValueSpecification
Figure 27: State View Metamodel
relation is an AND relation between the substituted transitions, meaning that in
order for the substituting transition to be triggered all these transitions should
be triggered in the specified order. This description of transition substitution is
translated by the sub-metamodel defined in Fig. 28.
substitutions
0..*
StateMachine
Transition
from
1
Substitution
- type: SubstitutionType
TransitionSubstitution
<<enumeration>>
SubstitutionType
- AND
- OR
1..* to
Figure 28: An excerpt of the State View Metamodel showing Transition Substitution.
55
Part V
State View Weaving
RAM allows the modeller to define stand-alone reusable aspect models using 3
modelling notations. Furthermore, it supports aspect dependency chain, which
allows an aspect providing complex functionality to reuse the functionality provided by other aspects. Hence complex models of any size can be built by
composing many interdependent, simple models using instantiation directives
that map model elements from one model to the other. However, specifying the
composition of RAM models using instantiation directives is a non-trivial task.
In this context, being able to merge two or more dependent models to create an
independent one can help a modeller see how these models interact with each
other and check the consistency of the specified instantiations and correct them
if they prove to be wrong. This facilitates the identification of errors early in
the design process which increases the quality of the software system.
Following this idea, TouchRAM currently allows a modeller to weave the
structure and message views of a RAM model. Weaving combines aspect models
together to a final woven model that has no dependencies. This final model can
then be transformed into an executable version, the final application.
In the case of RAM state views, the composition operator, i.e., CSP || composition, is easy to apply mentally. However this is not trivial for complex
aspect-oriented designs, where the structure and behaviour are defined across
many inter-dependent aspects. For this reason we decided to offer the modeller
the possibility of composing the partial behaviours of mapped classes together
to yield a woven state view, i.e., a state view describing the complete protocol.
Using the weaver, the modeller can validate the correctness and the consistency
of his partial models, and check if the composed aspect behaves as it is supposed
to behave.
Before describing the formalization of the state view weaving algorithm in
this chapter, we will briefly explain how weaving of structural views works. Understanding this process is essential, since weaving state view builds on structural view weaving.
9
Weaving Structural Views
In subsection 2.3.3, we gave an overview of the structure view weaving and we
showed briefly an example of how two dependant models can be woven together,
and also how a complete hierarchy of interdependent aspects can be woven to
create an independent model. In this section we will give more details on the
algorithm used to generate such models.
The existing weaver for structural views offers two different operations to the
user: complete weave and single weave. A complete weave refers to combining
all aspects that an aspect depends on directly or indirectly, resulting in an
aspect without any dependencies. When weaving completely, the order in which
56
aspects are woven together does not matter. A single weave refers to composing
two specific aspect models that are directly dependent on each other, i.e., one
aspect instantiates the other. On the one hand, this kind of weaving is needed
for understanding purposes, for example, when a modeller wants to see the result
of applying an aspect to another one. On the other hand, single weave allows
to weave an entire hierarchy step by step by successively taking the result of a
single weave and weaving another directly dependent aspect into it. Each step
requires an update of the instantiations directives, since the lower-level model
(the one woven into the other) might depend on other aspects.
Internally, the algorithm for complete weave is based on the algorithm used
for the single weave: performing a complete weave simply executes single weave
until there are no instantiations left in the high-level model and a model with
no dependencies is obtained.
In a single weave process, one aspect is called the base and the other the
dependee. The dependee is the aspect being instantiated by the base, and from
a semantic point of view the dependee is woven into the base.
The following steps summarize the process performed by the weaver when
weaving an aspect A (dependee) into an aspect B (base) as part of a single
weave:
1. Pre-process extends instantiations: In the case of an extension dependency (using extends), it is not mandatory to specify a mapping between
elements that have the same name. For example, the model StockExchangeGraph (see Fig. 5) extends the model StockExchange, however there are
no instantiation directives specified for this dependency. The mapping
between StockExchangeGraph Stock and StockExchange Stock is implicit. For this reason, this pre-process step consist in creating default
mappings for all classes in A, where a class with the same name in B exists. Moreover, for each class where such a mapping is created, also all its
operations are mapped.
2. Check for name clashes: In the structural view, class names must be
unique, i.e., two classes with the same name are not permitted. In the case
of a customization dependency (using depends), if this situation happens,
the weaving is aborted with an exception requiring the modeller to resolve
the conflict. The modeller can either rename the class or provide a mapping. However, if there are two classes with the same name representing
the same design, they are identical and are be merged. For example, an aspect can instantiate ZeroToMany-Ordered model twice. If |Associated
is mapped to the same class both times, this results in two Sequence
classes that are identical, because they have the same type. Hence, only
one Sequence class is propagated into the base model.
3. Weave: For all classes specified in the instantiation directives, the mapped
classes from A and B are merged. When merging classes, all attributes,
associations and information about super types are merged by copying
them from the class in A into the class in B. Operations, if they are not
57
aspect StockExchange depends on ZeroToMany-Ordered
structural view
Stock
- String name
- int price
+ Stock Stock(String name, int price)
+ String getName()
+ String setName()
+ setPrice(int price)
+ int getPrice()
~ Sequence<StockWindow> getObservers()
~ notifyObservers()
StockWindow
myStock
0..1
+ StockWindow StockWindow(Stock s)
~ updateWindow(Stock s)
~ startObserving(Stock)
~ stopObserving()
Instantiations:
ZeroToMany-Ordered: |Data → |Stock; |Associated → |StockWindow; getAssociated → getObservers
Figure 29: The Resulting Structural View of weaving the StockExchange model
into StockExchangeGraph.
mapped, are copied over as well. If no mapping was provided, the class
from A is copied into B including the containing elements. In this case, the
visibility of operations is changed from public to aspect-private to ensure
encapsulation of lower-level details [4].
4. Update instantiations: Because any two aspects in an aspect hierarchy
can be woven together, it is necessary to update the instantiations of the
dependee when copying them into the base. For our StockExchange example given in Section2.3.2, when weaving Observer into StockExchange,
the mappings of the latter must be updated to include the instantiations of
Observer, i.e., now StockExchange will depend directly on ZeroToMany-Ordered.
The resulting mappings are shown in Fig. 29.
The structure view weaver supports hierarchies of arbitrary depth. In the
case of a hierarchy of more than one level, as it is the case for the StockExchangeGraph model (see Fig. 6), a bottom-up weaving approach is followed. This approach starts by weaving the lower-level models of the hierarchy first, using a
single weave algorithm, and traverses the path up until it reaches the top-level
model. For example, applying such an approach to the StockExchangeGraph
model will results in the following steps:
1. The Traceable model is woven into the StockExchangeGraph model to
create StockExchangeGraph’
2. The ZeroToMany-Ordered model is woven with the model obtained in step
1, i.e., StockExchangeGraph’, to create StockExchangeGraph”
3. The ZeroToMany-Ordered model is woven into Observer to create Observer’
4. The resulting model Observer’ is woven into StockExchange to create
StockExchange’
58
5. StockExchange’ of step 4 is woven into the model obtained in step 2
(StockExchangeGraph”) to create the final independent model StockExchangeGraph”’.
10
Weaving State Views
Weaving of state views is performed by weaving the state machines of a state
view A into the state view B, where the classifier specified by A is mapped
to the classifier specified by B. Two state views are woven together only if the
classifiers whose protocols they specify are dependent, i.e., mapped to the same
entity.
10.1
State View Weaving Algorithm
The weaving process of state views is split into two phases. The first phase is
done for each two directly dependent aspects A and B that are woven together.
After weaving the structure view from A into B, for each state view StateView_A
of A, if the specified class Class_A is mapped to a class Class_B in B that has
a state view StateView_B, all the state machines of StateView_A are copied to
the state view StateView_B. Otherwise, i.e., if Class_B doesn’t have a state
view or if Class_A is not mapped to any class in B, the whole state view
StateView_A is copied over to B.
This first step prepares the ground for the second phase, where all state
machines of the resulting state views are woven together, i.e., the CSP || composition operator is applied. In the case where a modeller decides to weave
the state view and keep the state machines without applying the CSP composition operator, only phase one is performed. The main functions of the weaver
and the two phases of state view weaving are described in more details in the
following subsections.
10.1.1
General Overview
Single Weave A single weave weaves an aspect A into an aspect B. As both
aspects are directly dependent in a hierarchy, this means that B instantiated
A to reuse its functionality. Therefore, an instantiation for A exists in B describing class mappings. The algorithm for weaving two aspects is outlined in
Algorithm 1. First the dependency of the aspect B to the aspect A is resolved
(Line 2) and the result is an independent aspect with no reference to aspect
A. Second, the CSP || composition operator is applied to the state machines of
each state view of the resulting aspect (Line 3).
Algorithm 2 shows the definition of what it means to resolve the dependencies
between two aspects. This process is divided to two main steps. The first step
consist in weaving the structural view as described in section 9. The algorithmic
description for weaving the structure view is beyond the scope of this thesis. The
second step (Line 4) takes care of copying and merging the state views of the
aspect A (instantiation aspect) into the state views of the aspect B (the base
aspect).
59
Algorithm 1 Weaving two directly dependent aspects together (single weave)
1
2
3
4
5
f u n c t i o n WeaveSingle ( base , i n s t a n t i a t i o n )
ResolveDependency ( base , i n s t a n t i a t i o n )
WeaveStateViews ( b a s e )
return aspect
end f u n c t i o n
Algorithm 2 Resolving the Dependency between Two Directly Dependent Aspects
1
2
3
4
5
6
f u n c t i o n ResolveDependency ( base , i n s t a n t i a t i o n )
WeaveStructuralView ( base , i n s t a n t i a t i o n )
w e a v i n g I n f o <− weaving i n f o r m a t i o n o f s t r u c t u r a l view
CopyStateViews ( base , i n s t a n t i a t i o n , w e a v i n g I n f o )
return aspect
end f u n c t i o n
In order to be able to correctly copy state views, information about the
structural weaving process is required. In section 10.1.2, we explain the details
of copying state views and the importance of this information. The weaver
performing the structural view weaving has the knowledge of what element of an
aspect A is now which element in B. When instantiation directives are explicitly
specified, the element from A is merged with the element in B. Otherwise the
element from A is copied into B. This information is important for the state view
weaving, and hence the weaving of structural views keeps track of all elements
of A that have been merged into B. This “weaving information” produced by
the structural view weaver is used for message view weaving, and also in the
context of the state view weaving. The weaving information essentially consists
in a set of mappings from an element in A to a set of elements in B. The
set of elements is necessary, because an element can be mapped to more than
one element. An example of where this is required is StockExchange, which is
shown in Fig. 3. |modify is mapped to setName and setPrice. The mapping
will therefore look as follows: |modify → {setName, setPrice}. In order to be
able to access the mapping information, after weaving the structural view, the
weaving information is retrieved and passed to the CopyStateViews algorithm
(see Line 4 of Algorithm 2).
Complete Weave When performing a complete weave for a higher-level aspect C, the complete hierarchy of aspects that C depends on is woven into C.
Aspects are woven in depth-first order, meaning that the weaver starts with the
lowest-level aspect in the hierarchy, weaving it into its instantiator. This process of weaving an aspect to its instantiator is considered a single dependency
resolution as two directly dependent aspects in a hierarchy are woven together.
The complete dependency resolution of an aspect hierarchy is highlighted in
60
Algorithm 3 Resolving all dependencies of an aspect
1
2
3
4
5
6
7
8
9
f u n c t i o n ResolveDependencies ( base )
f o r a l l i n s t a n t i a t i o n i n i n s t a n t i a t i o n s o f b a s e do
i f i n s t a n t i a t i o n A s p e c t has i n s t a n t i a t i o n s
ResolveDependencies ( i n s t a n t i a t i o n A s p e c t )
end i f
ResolveDependency ( base , i n s t a n t i a t i o n )
end f o r
return aspect
end f u n c t i o n
Algorithm 3. Beginning from the highest level aspect C, all instantiations are
woven into it. In Line 6, the resolve dependency operation used in the single
weave is executed for those two aspects. This is only done once the instantiated
aspect (instantiationAspect) has no instantiations itself, i.e., is independent.
If an instantiated aspect has instantiations, the dependencies of that aspect are
resolved first. In Line 4, this process is repeated until no instantiations are left,
i.e., each aspect, the algorithm is executed for, is independent. The result is an
independent aspect.
Algorithm 4 shows the definition of the complete weave. Phase one is performed in line 2 by resolving all dependencies, weaving the structure and copying
all state views into this aspect. After all dependencies are resolved, phase two
is executed in Line 3 by weaving all state machines in the aspect state views.
The details of how state views are woven are described in Section 10.1.3.
Algorithm 4 Weaving an Aspect completely
1
2
3
4
5
f u n c t i o n WeaveComplete ( b a s e )
ResolveDependencies ( base )
WeaveStateViews ( b a s e )
return aspect
end f u n c t i o n
10.1.2
Copying State Views
Copying all state views from A (dependee aspect) into B (base aspect) has two
cases to take into consideration. The process is formally described in Algorithm 5.
• State machine copying: A classifier in A can have a state view specifying
its behaviour, and at the same time it can be mapped to another classifier
in B that has also its own state view. In this case state machines from
aspect A’s state view should be copied over to the existing state view of
the aspect B. Lines 10 to 13 of the Algorithm 5 handle this case. Copying
a state machine refers to creating a duplicate of it in the target state view.
61
Algorithm 5 Copying state views
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
f u n c t i o n CopyStateViews ( base , i n s t a n t i a t i o n , WeavingInfo )
f o r a l l i s v i n s t a t e V i e w s o f i n s t a n t i a t i o n A s p e c t do
b a s e C l a s s e s <− w e a v i n g I n f o [ i s v [ S p e c i f i e s ] ]
f o r a l l bc i n b a s e C l a s s e s do
bsv <− s t a t e view from b a s e s p e c i f y i n g bc
i f bsv doesn ’ t e x i s t
bsv <− CopyStateView ( bc , i s v , w e a v i n g I n f o )
add bsv t o t h e s t a t e v i e w s o f b a s e
else
f o r a l l ism i n s t a t e M a c h i n e s o f i s v do
bsm <− CopyStateMachine ( bc , ism , w e a v i n g I n f o )
add bsm t o t h e s t a t e machines o f bsv
end f o r
end i f
end f o r
end f o r
return base
end f u n c t i o n
This requires copying states and transitions. Copying states is a straightforward process since the only attribute a state has is its name. Copying a
transition requires another step besides copying the state of a transition,
namely updating the references of the transition. The metamodel of state
views contains references to elements of the structural view. When copying a state view from the lower-level aspect A to the higher-level (base)
aspect B, the references still point to the elements in A. Therefore it is necessary to update these references. The elements that are referenced in the
transition are operations which are referenced in the signature property
of Transition. For example, when weaving ZeroToManyOrdered into
Tracing, the class |Data is merged with Context. The state machines
of the state view of |Data reference this class’operations in the property
signature of each transition. The transition add, for example, references the operation add of the class contained in the structural view of
ZeroToManyOrdered. However, after copying the state machines of |Data
into the state view of Context, all these references must be updated to
point to the operations of the class Context instead. Additionally, after
weaving, add transition should point to the operation addTrace.
As described in the beginning of this section, when weaving the structural
view, the knowledge of what element in A is now which element in B is
kept in the weaving information. Therefore, when updating references,
for each affected element it just has to be checked whether the current
referenced element is contained in the mapping as a key. If so, it has been
replaced by the value of the mapping. An example of how this is done for
a state view is described in Algorithm 6 where a transition is copied and
added to the new copy of the state machine. A special case exists when an
operation was mapped more than once, e.g. |modify in StockExchange.
62
In this case a transition is created for each mapped operation (Line 4 to
10).
Algorithm 6 Transition copying
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
f u n c t i o n C o p y T r a n s i t i o n ( c l a s s i f i e r , smCopy , tranToCopy , w e a v i n g I n f o )
i f tranToCopy has a s i g n a t u r e
mappedOperations <− w e a v i n g I n f o [ tranToCopy [ s i g n a t u r e ] ]
f o r a l l op i n mappedOperations do
i f c l a s s i f i e r c o n t a i n s op
tCopy <− copy tranToCopy
tCopy [ s i g n a t u r e ] <− op
add tCopy t o t h e t r a n s i t i o n s o f smCopy
end i f
end f o r
else
tCopy <− copy tranToCopy
add tCopy t o t h e t r a n s i t i o n s o f smCopy
end i f
end f u n c t i o n
• State view copying: A classifier from A can have a state view specifying
its behaviour and it can be mapped to a classifier from B that has no state
view or it can be not mapped at all to any classifier in B. In this case the
whole state view should be copied over to the aspect B. Lines 6 to 8 of the
Algorithm 5 describe this case. A state view has two properties: specifies,
which is a reference to one of the classifiers in the structural view, and
stateMachines, a list of state machines. Therefor copying a state view
means creating a copy of all its state machines (for this the operation
CopyStateMachine in Line 11 of Algorithm 5 can be reused) and set the
specifies attribute to the updated reference.
10.1.3
Weaving
Once the preliminary work is done, all state views are contained in the highestlevel aspect. It is then possible to compose their state machines together by
applying the CSP || composition operator. The formal procedure of weaving
two state machines is described in Algorithm 7. Fig. 30 shows the result of
composing two state machines from the aspect Tracing.
The main idea is to start from the start states of the two state machines to
compose (SM1 and SM2) and process their outgoing transitions. To do this we
need two data structures to keep track of important information:
• statesEquivalence: a data structure that stores the mapping between
a state in the woven state machine and its equivalent states from SM1 and
SM2. For example, an entry in this data structure could be Idle_NoTraces
-> (Idle, NoTraces), where Idle_NoTraces is a state from the woven
state machine (state machine at the bottom of Fig. 30), and the Idle state
63
addParticipant
addTrace
removeTrace removeTraces
Context
Idle
Active
[size == 0]
TraceAvailable
NoTraces
contextCompleted
removeParticipant
Context
addTrace
addTrace
Completed
Context
contextCompleted
Completed_NoTraces
addParticipant
Idle_NoTraces
Active_NoTraces
removeParticipant
[size == 0]
addTrace
addTrace
contextCompleted
Completed_TracesAvailable
[size == 0]
[size == 0]
Idle_TraceAvailable
addParticipant
Active_TraceAvailable
removeParticipant
removeTraces
removeTrace
removeTraces removeTrace
removeTraces
removeTrace
Figure 30: Applying CSP composition operator
comes from SM1 (top-left corner of Fig. 30) and the NoTraces state from
SM2 (top-right corner of Fig. 30).
• statesToProcess: a list of states that belong to the woven state machine
and whose outgoing transitions have not been processed yet.
Each state wState in the woven state machine is a combination of two states s1
and s2 from SM1 and SM2. Therefore, the outgoing transitions of the woven
state machine can be described as follows:
s1[outgoings] U s2[outgoings] \ {not allowed transitions according to CSP}. The
only situation where a transition from the union of the outgoing transitions of
s1 and s2 is not allowed is when this transition belongs to the outgoings of only
one of these states, i.e., only s1, and at the same time belongs to the alphabet
of the other state machine, i.e., SM2. In Line 17 and 19 of Algorithm 7, the
processing of the outgoing transitions of s1 and s2 is done in consequence.
Algorithm 8 gives an overview of how states and transitions are added to
the woven machine according to the outgoing transitions of two states, s1 and
s2, from sm1 and sm2, the two state machines being composed.
There are two cases where a transition can be accepted and added to the
woven state machine:
• The transition tr belongs to the outgoing transitions of the first state
eqS1 and at the same time to the outgoing transitions of the second state
eqS2. The transition tr is added to the outgoing transitions of the woven
64
Algorithm 7 State machines weaving
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
f u n c t i o n WeaveStateMachines ( sm1 , sm2 )
wovenSM <− c r e a t e a new s t a t e machine
s t a t e s T o P r o c e s s <− c r e a t e a l i s t
s t a r t S t a t e <− c r e a t e a new s t a t e
s t a t e s E q u i v a l e n c e <− a mapping between a s t a t e from wovenSM t o
two s t a t e s one from sm1 and one from sm2
add s t a r t S t a t e t o s t a t e s T o P r o c e s s
add ( s t a r t S t a t e , <sm1 [ s t a r t S t a t e ] , sm2 [ s t a r t S t a t e ] >) t o
statesEquivalence
While s t a t e s T o P r o c e s s i s not empty do
s 1 <− t h e e q u i v a l e n t s t a t e t o s t a t e s T o P r o c e s s [ 0 ] from sm1
s 2 <− t h e e q u i v a l e n t s t a t e t o s t a t e s T o P r o c e s s [ 0 ] from sm2
P r o c e s s O u t g o i n g T r a n s i t i o n s ( s t a t e s T o P r o c e s s , s1 , s2 ,
wovenSM , sm1 , sm2 )
P r o c e s s O u t g o i n g T r a n s i t i o n s ( s t a t e s T o P r o c e s s , s2 , s1 ,
wovenSM , sm2 , sm1 )
remove s t a t e s T o P r o c e s s [ 0 ] from s t a t e s T o P r o c e s s
end While
end f u n c t i o n
state (Line 18) and in this case the resulting state endState1 of triggering
tr in sm1 and the one, endState2, resulting from triggering tr in sm2
are combined to create a new woven state (Line 11). In the example in
Fig. 30, when eqS1 is the state Active and eqS2 is the state NoTraces
and tr is the transition addTrace, the latter can be accepted and added
to the woven machine. The start woven state of the new added transition
is the combined state of Active and NoTraces, i.e. Active_NoTraces,
and the end woven state, wEndState, is the combination of the end state
of addTrace in the first machine, which is Active, and in the second
machine, which is TraceAvailabe.
• The transition tr belongs to the outgoing transitions of the first state
eqS1, however it does not belong to the outgoing transitions of the second
state nor to the general alphabet of the second state machine sm2. In this
case, the only difference with the previous case is that the end state of the
added transition is the combination between the end state of tr in the
first state machine and eqS2 (Line 7). As an example, we can take the
case of the states Idle and NoTraces and the transition addParticipant,
the latter belongs to the outgoing transitions of Idle, but does not belong to the alphabet of the second machine. Thus, the woven end state,
wEndState, is the combination of the state Active, which is the end state
of addParticipant, and NoTraces.
65
Algorithm 8 Process Outgoing Transition
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
29
30
31
f u n c t i o n P r o c e s s O u t g o i n g T r a n s i t i o n s ( s t a t e s T o P r o c e s s , eqS1 , eqS2 ,
wovenSM , sm1 , sm2 )
ws <− s t a t e s T o P r o c e s s [ 0 ]
For a l l t r 1 i n eqS1 [ o u t g o i n g s ] do
I f t r 1 doesn ’ t a l r e a d y e x i s t i n wS [ o u t g o i n g s ] then
t r 2 <− t h e e q u a l t r a n s i t i o n t o t r 1 from eqS2 [ o u t g o i n g s ]
canAccept <− f a l s e
stateToCombine <− eqS2
I f tr2 exist
then
stateToCombine <− t r 2 [ e n d S t a t e ]
I f t r 2 e x i s t o r sm2 doesn ’ t c o n t a i n t r 1 then
wTr <− copy t r 1
add wTr t o wS [ o u t g o i n g s ]
wEndState <− e q u i v a l e n t s t a t e t o t r 1 [ e n d S t a t e ] and
stateToCombine from wovenSM [ s t a t e s ]
I f wEndState e x i s t s then
add wTr t o wEndState [ i n c o m i n g s ]
else
wEndState <− c r e a t e new s t a t e
add wTr t o wEndState [ i n c o m i n g s ]
add ( wEndState ,< t r 1 [ e n d S t a t e ] , stateToCombine >) t o
statesEquivalence
add wEndState t o s t a t e s T o P r o c e s s
end I f
end I f
end I f
end For
end f u n c t i o n
When processing a pair of states s1 and s2 - where s1 belongs to SM1 and
s2 belongs to SM2 - the outgoing transitions of s1 will be processed first using
the Algorithm 8 and after that those of s2 will follow. For this reason, if both
states has a common transition, it is important to check if this transition was
not already added to the woven state machine (Line 4) to avoid adding it twice.
Moreover, before creating the new end woven state, wEndState, we should
first check if the state was not already added to the woven state machine. This
is done using the statesEquivalence data structure (Line 20).
66
Part VI
State View Support for
TouchRAM
The previous steps – namely the definition in Chapter IV of a metamodel for
state views and in Chapter V of a weaving algorithm for state views – have prepared the ground for the integration of modelling and weaving state views into
TouchRAM, the multi-touch enabled tool of the Reusable Aspect Models
approach. In this Chapter, we first present an overview of the TouchRAM
architecture. Second, some details about the integration of the state view modelling support into TouchRAM are given.
11
Overview of TouchRAM
The TouchRAM tool gives the designer access to a vast library of reusable
design models encoding essential recurring design concerns. It exploits model
interfaces and aspect-oriented model weaving to enable the designer to rapidly
apply reusable design concerns within the design model of the software under
development. The user interface features of the tool are specifically designed for
ease of use, reuse and agility.
In Fig. 31, an overview of the architecture of TouchRAM is presented.
The TouchRAM architecture follows a Model-View-Controller (MVC) pattern.
The tool is divided into three major components: the graphical user interface
(GUI) representing the View, the Controller and RAM weaver representing the
Controller layer and finally the RAM metamodel and its instances representing
the Model.
11.1
11.1.1
Frameworks Used by TouchRAM
Eclipse Modelling Framework
The Eclipse Modelling Framework (EMF) [13] is an Eclipse project offering
a model-driven approach to create structured data models that can be used
within applications. It allows to define metamodels based on Ecore, a subset of
the Meta Object Facility (MOF) specified by the Object Management Group
(OMG) [19]. Ecore is very close to Essential MOF (EMOF). The Ecore notation
is similar to a UML class diagram. An Ecore model (i.e., an instance of Ecore)
defines the metamodel of a desired data structure. EMF provides facilities to
generate different Java code from the defined metamodel:
• Model code that represents the model defined in Ecore,
• Edit code which provides adapter classes that offer viewing and commandbased editing (e.g., for undo/redo) of the model,
67
TouchRAM Architecture
TouchRAM GUI
Runner
<<use>>
Handlers
has
Views
handles
events
<<extend>>
TouchRAM
Components
<<use>>
MT4j
extends MT4j components
retrieves textual representation, editable values, choice of values
notifies about changes
calls to weave
model
calls to request
changes to model
registers as listener
Weaver
Controller
Weaver
Controllers
Edit (generated)
Adapter
(ItemProvider)
creates
commands
EMF.Edit
Command
(part of EMF.Edit)
execute commands
updates
notifies
Model (generated from meta-model)
RAM Model
Interfaces
<<implements>>
RAM Model
Classes
EMF
Figure 31: Architecture of TouchRAM
• A generic Editor supporting the creation, viewing and editing of models,
and
• Test code allowing the generation of test cases that can be further extended.
The code is generated as Eclipse plug-ins facilitating to be used in Eclipse applications, but can also be used in standalone Java applications. Furthermore,
EMF provides serialization in the XML Metadata Interchange (XMI) format.
The model-driven mechanism allows to modify the metamodel at any time and
re-generate code. Generated code can be modified and marked in order for the
generator to skip re-generating it and leave it intact when generating code again.
11.1.2
Multitouch for Java (MT4j)
Multitouch for Java (MT4j) [17] is an open source Java framework with a special
focus on multi-touch. The framework supports creating visual applications in 2D
or 3D using OpenGL for software or hardware accelerated graphics rendering.
It is cross-platform compatible allowing to be run on the latest Windows, Linux
(Ubuntu) and Mac OSX operating systems. MT4j is designed to support a wide
range of input devices including multi-touch enabled ones. Besides the latest
multi-touch software and devices in consumer electronics such as Windows 7
and Apples multi-touch enabled trackpad, it supports the TUIO (Tangible User
68
Interface Objects) protocol. Furthermore, regular mouse and keyboard can be
used as well, and by providing an extensible event stack, different input methods
can be used simultaneously. Additionally, MT4j provides an extensible multitouch gesture system with pre-defined common gestures and pre-built multitouch enabled user interface components.
11.2
TouchRAM Implementation
The GUI of TouchRAM is realized using MT4j. The UI components of MT4j
were extended for TouchRAM in order to support the developer. Moreover, to
enhance the decoupling of the user interface (UI) from the other components,
EMFs built-in notification mechanism is used to observe the model and notify
the user interface of any changes.
The metamodel defines the abstract syntax for RAM models and is defined
as an Ecore model. This allows TouchRAM to use the generated code as the
base for creating and manipulating models, and to serialize RAM models into
XMI.
The controllers are used to send commands to the Model to update its state.
To facilitate automatic undo/redo functionality, the generated Edit code is used.
Instead of modifying the model elements directly by calling the appropriate setter methods, commands are created and executed on a command stack. Furthermore, the generated Edit code contains an adapter class for each class in
the metamodel. Adapters are required by EMFs facility when using commandbased editing. In addition, adapters provide more functionality, such as a label
provider with the method getText to retrieve a textual representation of a given
object. Making use of the provided functionality leads to a better separation of
concerns, higher code quality and makes it easier for the developer to implement
the user interface.
The weaver is a separate module of the controller layer that is invoked by
the GUI on command of the user. This module performs the weaving process
of a model. It is implemented with Java and uses the generated Model code
to create a woven model that will be displayed by the UI. Section 12.3presents
more details about this module.
The current version of TouchRAM is capable of creating aspects with a
structural view and weaving the structural view of aspects. There is no support
for message view creation, however if the message views are defined using the
provided editor of EMF, the tool is capable of displaying them and performing
the weaving of message views. Fig. 32 shows TouchRAM and the visualization
of the structural view of the Tracing model (Fig. 13).
12
Integration of State Views into TouchRAM
The Integration of state views into TouchRAM required changes to various
components of the tool. All the components make use of the code generated
from the metamodel, for this reason the first step was to integrate the metamodel
69
Figure 32: The Tracing Model in TouchRAM
Figure 33: Context State View of the Tracing Model displayed in TouchRAM
presented in section 8 with the RAM Ecore model. Changing the Ecore model
made it possible to generate new Model code and Edit code with added state
view elements. The following sections shows how the other components were
extended to support the creation and editing of state views.
12.1
State View GUI
When displaying an aspect, only the structural view and the message views were
shown previously. Therefore, an additional button was introduced allowing the
user to switch from message views to state views. Switching hides the current
view and shows the state view.
Fig. 33 shows the state view of the class Context from the Tracing model
(see Fig. 13, 17 and 18).
70
12.1.1
Views
For each element of a state view that has to be created and visualized, a view
class is specified. Each view is responsible for visualizing that particular element. The different elements of a state view are: state view, state machine,
state and transition. Thus, a StateViewView class was created as the graphical
representation of a state view, a StateMachineView was created as the graphical
representation of a state machine, etc.
Each view is responsible for instantiating and deleting its composing elements, e.g., a StateMachineView is responsible for instantiating the views of its
states and transitions. To be able to do that, each view keeps a mapping between the model class, i.e., the representation of the model object in the Model
code, and the view class of its components. This way when a notification is
received from the adapters in the Edit code specifying a deletion of a model element, the view will be able to identify the right view representing this element
and to remove it from the GUI.
A model in RAM can have many state views, and a state view doesn’t have
an explicit container other than the aspect itself. For this reason, a StateDiagramView was created where the different StateViewView creation and deletion
is handled.
All views are an extension of MT4j shapes, mainly MTRectangle and MTLine. Furthermore, they implement the interface INotifyChangedListener, an
interface provided by Edit code, to be able to receive the notification of model
changes, i.e., deletion, addition, modification.
We noticed that the AssociationView used to represent an association element in the structural view has common properties with the TransitionView.
An association creates a relation between two classes and a transition creates
a relation between two states. Thus, we decided to reuse the AssociationView
code. The common functionalities between the two views were moved to an
abstract class, RelationshipView, and the two views now extend this abstract
class.
12.1.2
Handlers
Each view class is associated with an event handler, e.g., StateMachineView is
associated with StateMachineViewHandler, etc. Each handler inherits from the
MT4j interface IGestureEventListener, to be able to receive and process the
GUI events - A list of the different user commands can be found in the Annexe.
Once an event is received by the handler it will be forwarded to the appropriate
controller, with the appropriate information, to be processed.
12.1.3
Layouts
All state views are added to a container, which places the state views one below
the other. As it was mentioned before, the container of an element is responsible
for creating the element and placing it at the appropriate position.
71
One extension of TouchRAM for MT4j is the introduction of layouts. Each
view class inherits from RamRectangleComponent, which is an extension of the
MT4j class MTRectangle and offers some general features such as automatic
child resizing and handling of events. Currently, horizontal and vertical layouts are defined that place the elements either in a column vertically or a row
horizontally. The layouts additionally take care of the size of elements.
StateDiagramView and StateViewView make use of the vertical layout to
place the different StateViewViews and StateMachineViews one above the other.
However, state machines cannot make use of those layouts because the elements,
i.e., states and transitions, have to be placed in a more flexible way. They
might even overlap each other. For this reason and to avoid setting the width
and height of an element explicitly, a layout, StateMachineLayout, for state
machines was created where the dimensions of a state machine are adjusted to
fit its content, i.e., states and transitions.
Thanks to the state machine layout, the user is able to place the different
elements of a state machine in such a way that they do not overlap, and he
also can move them around at will. Whenever the user repositions states, the
dimension of the state machine are automatically adjusted accordingly by the
state machine layout. However, in the case where the model is generated using
the EMF editor, or more importantly when the woven model is generated, the
position of the states are not defined. In such a case, to avoid that the states
overlap, a simple solution was chosen. The states are positioned vertically with
a fixed space between them. In the future, the state machine default layout
should be improved to determine a better positioning of states when they are
automatically generated or created without an initial layout.
12.2
State View Controller
Controllers in TouchRAM are responsible of transforming the events received
from the GUI to commands that use the Edit code to make the appropriate
changes to the model. Controllers are singletons. Each element of the state view
has a controller associated with it to handle creation, deletion, modification and
repositioning events.
12.3
State View Weaver
Previously, the weaver consisted of the structure and message view weaver. In
Section 10 we described the overall weaving process consisting of weaving the
structural view and state views. A general weaver was introduced, RAMWeaver,
which is responsible for orchestrating the weaving process and calling the StructuralViewWeaver and the MessageViewWeaver. Fig. 34 depicts the overview of
the weaver architecture. Integrating the StateViewWeaver into this new structure was a straightforward process. The weaving information needed for performing the weaving of state views successfully as described in Section 10 is
provided by the StructuralViewWeaver.
72
RAMWeaver
StructuralViewWeaver
+ weaveAll(Aspect base): void
+ weaveSingle(Aspect base, Instantiation instantiation) : void
- resolveDependencies() : void
+ weaveSingle(Aspect base, Instantiation instantiation) : Aspect 1
+ getWeavingInformation(): WeavingInformation
structuralViewWeaver
weavingInformation
1
1
messageViewWeaver
MessageViewWeaver
1
WeavingInformation
- wovenObjects : Map<Object, Set<Object>>
+ addWovenObject<T>(T old, T new) : void
+ getWovenObject<T>(T old) : T
+ getWovenObjects<T>(T old) : Set<T>
+ contains(Object object) : boolean
+ hasValue(Object object) : boolean
+ copyMessageViews(Aspect base, Aspect dependee,
WeavingInformation wInfo) : void
+ weaveMessageViews(Aspect base, WeavingInformation
wInfo) : void
StateViewWeaver
StateViewWeaverUtils
1
StateViewWeaver
+ copyStateViews(Aspect base, Aspect dependee,
WeavingInformation wInfo) : void
- CopyStateView(Classifier cl, StateView sv,
WeavingInformation wInfo): StateView
- CopyStateMachine(Classifier cl, StateMachine sm,
WeavingInformation wInfo): StateMachine
- CopyState(State state)
- CopyTransition(Classifer cl, StateMachine sm, Transition t,
WeavingInformation wInfo): void
+ weaveStateViews(Aspect base) : void
- weaveStateMachines(StateMachine stateMachine1,
StateMachine stateMachine2): void
- processOutgoingTransitions(StateEquivalence se, StateMachine
wSM, StateMachine sm1, StateMachine sm2, int index)
Figure 34: The Structure of the Weaver Component
The processes of copying and weaving state views were split into two classes
StateViewWeaverUtils and StateViewWeaver. StateViewWeaverUtils is a static
class that has one public method, i.e., CopyStateViews, which is called by the
public method weaveSingle of RAMWeaver.
As mentioned briefly in section 10, a modeller has three choices of how to
weave state views:
• Weave All: This choice generates a complete, independent woven model
that combines all the structure, behaviour and protocols of the entire aspect hierarchy. From the state view perspective, all the state views of
the instantiated aspects are copied to the woven model using the StateViewWeaverUtils methods. After that, using the StateViewWeaver methods, the CSP composition operator is applied to the different state machines of each state view to leave in the end only one state machine per
state view.
• Weave No CSP: When a class is complex and has many states and
transitions describing its behaviour, generating a woven state view with
a complicated state machine is not always the best way of presenting a
protocol to a modeller, since a single, big, woven state machine is often
hard to understand and analyse. For this reason, a modeller is offered
the option of weaving a model with its dependencies without applying the
CSP composition. In this case, all state views are copied over to the woven
model, merged with the existing state views and all references are updated
73
using StateViewWeaverUtils. However, the step of using StateViewWeaver
to apply the CSP composition operator is omitted. We believe that such
an option can help the modeller in the process of designing a state view.
Displaying in one place all the existing state machines5 related to the state
view to be modelled, can help the modeller to discover new constraints
that need to be added or even new state machines that need to be created
to orchestrate the behaviour of the instantiated models.
• Apply CSP: The last choice is a case that does not involve weaving any
other aspect model into the base model. When modelling the protocol of
a class using separate state machines, a modeller has to mentally apply
CSP composition to the state machines. Using only the methods provided
by StateViewWeaver, TouchRAM can now generate the composed state
machine upon request.
These three ways of weaving were implemented in the TouchRAM tool, and a
button for each option was created. The “Weave All ” button already existed as
part of the structural view as shown in Fig. 32. The “Apply CSP” and “Weave
No CSP” buttons were added to the right menu of the state view scene only,
since they are not applicable to the message and structural views.
5 State
machines copied from the instantiated aspects
74
Part VII
Conclusion And Future Work
This thesis presented a formal definition of state views in the Reusable Aspect
Models approach and showed the transformation of this definition from theory
to practice in order to enable tool support of state views.
We provided insight on the benefits that modelling of invocation protocols
can have when used in combination with behavioural specifications expressed
using sequence diagrams. Concretely, we showed how we applied this technique
to augment the RAM approach, which expresses the structure of software design
concerns within structural views based on class diagrams and the behaviour of
software design concerns using sequence diagrams, with additional state views
that describe invocation protocols. We detailed why Protocol Modelling, a
compositional modelling approach based on state diagrams, is an ideal notation
to specify such a protocol view, and show how we added support for protocol
modelling to the RAM metamodel.
We explained that the new state views can be used to assist the modeller
in the model composition specification task, and discussed how to use the new
protocol view by example. The Tracing and Checkpointable examples were
extracted from the AspectOPTIMA [6, 30] case study. In this thesis we did
not feel the need to integrate all PM features into the RAM state views. For
instance, we did not need to use derived states defined by PM for any of the examples presented in this thesis. As a next step, to demonstrate the effectiveness
of our state view approach, to analyze its strengths and limits, and to determine
if additional features need to be included in the approach to be fully general,
it is important to apply the RAM approach to the whole AspectOPTIMA case
study. The complexity of this case study will help us discover any shortcomings,
and lead us to improve the technique, if needed.
In order to facilitate the conversion of models defined using other UML
tools to be able to reuse them using RAM tool, we based our metamodel on
the UML metamodel of state machine diagrams and extended it with a higher
level of detail. A high emphasis was set on defining a complete and adequate
metamodel. First, we made sure that the state view metamodel elements that
were added are well-integrated with the already existing elements related to
the structural and message view. Second, it was important that the defined
metamodel expresses and covers all aspects of PM that we need in a concise way.
Finally, the metamodel had to be organized in such a way that the weaver can
efficiently manipulate RAM models, and that the TouchRAM tool can efficiently
display them. Up to now the metamodel defined in this thesis is sufficient and
no further work is needed. However, if new PM features such as derived states
are to be added to the state view, the metamodel needs to be adapted.
We specified a weaving algorithm for the state views and integrated it with
the general weaving process alongside the structural view and message views
weaving. The weaver allows a designer to weave a complete aspect hierarchy or
75
two directly dependent aspects in a hierarchy together. We described different
ways of applying the weaver selectively to RAM models to help the modeller
understand aspect hierarchies. The weaver was designed in such a way that it
offers different options of how the resulting woven state view can be presented
to the modeller. To enhance conciseness and facilitate coupling protocols when
composing, a sort of transition equivalence was introduced to the RAM state
views and it was integrated into the metamodel. However, the weaver, in its
current state, does not support this feature. As a future work, the weaver should
take into consideration this kind of mappings.
The definition of the metamodel and the weaver facilitated the integration of
state view support into TouchRAM, the tool for the Reusable Aspect Models
approach. The metamodel was defined using the Eclipse Modelling Framework and the weaver implemented with the Java framework. Furthermore, the
graphical user interface of TouchRAM was extended with state view creation
and editing capabilities, allowing a designer to create and modify existent state
views. Further ameliorations to the integrated state view support should be
done, ranging from layout improvements to providing more intuitive “user commands” in order to improve the TouchRAM tool user experience.
Two possible ways were described for weaving models in RAM – single weave
and weave all – . The “Weave all” option for the state views was integrated
into the TouchRAM tool. However, weaving selectively two state views of
two interdependent aspects is not yet implemented. Moreover, the different
options of using the state view weaver to present the woven state view were
integrated into the tool. However, while these options provide the modeller
with an alternative presentation of the woven state view, they do not solve the
problem of understanding such a woven model. The resulting woven state view
is a flat protocol model. To improve understanding of protocols, we imagine
the TouchRAM tool to allow the modeller to reorganize the states of the woven
protocol machine by aspects. Using hierarchy in this context can be useful.
The structure of of one of the composed protocol machines could be used as the
dominant hierarchy. This means that the behaviour of a class can be displayed
differently according to the functionalities it provides. Let’s take the example
of the class Context in the model Tracing. The woven protocol machine of this
class can be reorganized to be displayed according to the ExecutionContext
functionality or to the ZeroToMany-Ordered functionality. In order to do that,
composed states should be introduced. This kind of states will help combining
states by functionality, e.g., when the behaviour of the class Context is displayed
according to the ExecutionContext functionality, three composed states will be
displayed: Idle, Active and Completed. Selecting the Idle state will show two
sub-states: NoTraces and TracesAvailable. We believe that providing such a
reorganization feature will allow the modeller to understand better the modelled
behaviour.
The aim of integrating another behavioural view into RAM was mainly to
be able to exploit it to verify the correctness of compositions. Specifying the
composition of RAM models using instantiation directives is a non-trivial task,
in particular when it comes to specifying the composition of behaviour. Be76
havioural composition of sequence diagrams in RAM is asymmetric in nature.
One sequence diagram can invoke an operation that is defined by another sequence diagram, which means that the weaver has to insert the behaviour of
the called operation into the sequence diagram that made the call. Furthermore, aspect message views can modify the behaviour of a sequence diagrams
by adding additional behaviour before or after the already existing sequence of
interactions. To understand the resulting behaviour becomes tricky, in particular if the different behavioural specifications are scattered in multiple models.
Also, as for all asymmetric approaches, the order of composition matters in the
case where several aspect models want to add behaviour at the same place. As
a future work, consistency checking between the behaviour described by the
message views and the one described by the state views should be performed by
the TouchRAM tool to verify the behavioural specifications that cross model
boundaries.
77
Appendix
Action
Create a State View
Command
Tap and hold on the
background.
Delete a State View
Tap and hold on the keyword
"State View" and press the “X”
button.
Tap and hold on the keyword
"State View" and press the
“M+” button.
Tap and hold on the white space
(representing the state machine)
under the state view title.
Tap and hold on the state and
select the “Delete” button.
Create a State Machine
Create a State
Delete a State
Set a State as Start state
Create a Transition
Delete a Transition
Change a Transition
direction
Tap and hold on the state and
select the “Set Start” button.
1- Tap and hold over the start
state (to display the edit mode
of the state)
2- select the end state
(preferably select the borders of
the state).
3-Tap the text box to select the
operation OR
Tap and hold on the text box
and enter the name of the
operation.
Double tap on the arrow and
select the “Delete” button.
Tap and hold on the arrow.
Comment
- The state view name can
be entered or
- The keyboard dismissed
and the text box is double
tapped to get the list of the
classes. If the selected class
already has a state view
nothing will happen.
If the state deleted is the last
one, the state machine will
be deleted with it.
To enter a constraint type
first the character “/”
followed by the constraint,
e.g., size==0.
Table 1: List of User Commands for the TouchRAM State View
78
References
[1] Object-Oriented Technology. ECOOP 2007 Workshop Reader. Springer,
2007.
[2] AspectJ in Action: Enterprise AOP with Spring Applications. Manning
Publications, 2009.
[3] Wisam Al Abed and Jörg Kienzle. Information hiding and aspect-oriented
modeling. 14th Aspect-Oriented Modeling Workshop, Denver, CO, USA:1–
6, Oct. 2009.
[4] Wisam Al Abed and Jorg Kienzle. Information hiding and aspect-oriented
modeling. In: 14th Aspect-Oriented Modeling Workshop, Denver, CO,
USA., pages 1–6, Oct. 2009.
[5] Abir Ayed and Jorg Kienzle. Integrating protocol modelling into reusable
aspect models. Proceedings of the 5th ACM SIGCHI Annual International
Workshop on Behaviour Modelling - Foundations and Applications, 2013.
[6] G. Bölükbasi. Aspectual decomposition of transactions. Master’s thesis,
School of Computer Science, McGill University, Montreal, Canada, 2007.
[7] S. Clarke, W. Harrison, H. Ossher, and P. Tarr. Subject-oriented design:
Towards improved alignment of requirements, design and code. In 14th
Conf. Object-oriented Programming, Systems, Languages, and Applications
(OOPSLA), (Denver), (ACM, 325–339), 1999.
[8] Siobhan Clarke and Elisa Baniassad. Aspect-Oriented Analysis and Design:
The Theme Approach. 2005.
[9] S. Clarket and R.J. Walker. Composition patterns: An approach to designing reusable aspects. Proceedings of the 23rd International Conference on
Software Engineering (ICSE 2001), pages 5–14.
[10] Thomas Cottenier, Aswin Van Den Berg, and Tzilla Elrad. The motorola
weavr: Model weaving in a large industrial context. In: Proceedings of
the International Conference on Aspect-Oriented Software Development,
Industry Track., AOSD ’06. Bonn, Germany: ACM, Mar. 2006.
[11] Tzilla Elrad, Omar Aldawud, and Atef Bader. Aspect-oriented modeling:
Bridging the gap between implementation and design. Generative Programming and Component Engineering, 2487:189–201, 2002.
[12] Tzilla Elrad, Atef Bader, Mark Mahoney, and Omar Aldawud. Using aspects to abstract and modularize statecharts. 2004.
[13] David Steinberg et al. Emf: Eclipse modeling framework. 2nd. Boston,
MA, USA: Addison-Wesley Professional., 2009.
79
[14] Erich Gamma et al. Design patterns: Elements of reusable object-oriented
software. Boston, MA, USA: Addison-Wesley, 1995.
[15] Gunter Mussbacher et al. Requirements Modeling with the Aspectoriented
User Requirements Notation (AoURN): A Case Study. 2010.
[16] Robert E. Filman and Daniel P. Friedman. Aspect-oriented programming
is quantification and obliviousness. Aspect-Oriented Software Development.
Ed. by Robert E. Filman et al. Boston: Addison- Wesley, pages 21–35, 2005.
[17] The Fraunhofer Institute for Industrial Engineering IAO. MT4j – Multitouch For Java., volume url: http://www.mt4j.org. July 2012.
[18] Jim Gray and Andreas Reuter. Transaction Processing: Concepts and
Techniques. Morgan Kaufmann, 1993.
[19] Object Management Group. OMG Unified Modeling Language (OMG
UML), Superstructure. August 2011.
[20] W. Harrison, H. Ossher, and P. Tarr. Software engineering tools and environments: A roadmap. In Conf. Future of Software Engineering (Limerick),
pages 261–277, 2000.
[21] C. Hoare. Communicating Sequential Processes. Prentice-Hall International, 1985.
[22] Gregor Kiczales, John Lamping, Anurag Mendhekar, Chris Maeda, Cristina
Lopes, Jean marc Loingtier, and John Irwin. Aspect-oriented programming.
ECOOP, 1997.
[23] Jörg Kienzle, Wisam Al Abed, and Jacques Klein. Aspect-Oriented MultiView Modeling. In Proceedings of the 8th International Conference on
Aspect-Oriented Software Development - AOSD 2009, March 1 - 6, 2009,
pages 87 – 98. ACM Press, March 2009.
[24] A. McNeile and N. Simons. Protocol modelling: A modelling approach that
supports reusable behavioural abstractions. Software and System Modeling,
5(1):91–107, 2006.
[25] Ashley McNeile and Ella Roubtsova. Composition Semantics for Executable
and Evolvable Behavioral Modeling in MDA. 2009.
[26] Ashley McNeile and Ella Roubtsova. Aspect-oriented development using
protocol modeling. Transactions on aspect-oriented software development
VII, pages 115–150, 2010.
[27] Object Management Group. Unified Modeling Language: Superstructure (v
2.4.1). December 2011.
80
[28] Birger Møller-Pedersen Ole Lehrmann Madsen and Kristen Nygaard.
Object-oriented programming in the beta programming language. AddisonWesley, Reading, Massachusetts., 1993.
[29] Awais Rashid and Harold Ossher, editors. Transactions on Aspect-Oriented
Development (TAOSD VI), Special Issue on Dependencies and Interactions
with Aspects, volume 5490 of LNCS. Springer, 2009.
[30] McGill Software Engineering Laboratory (SEL).
http://aspectoptima.cs.mcgill.ca/, 2007.
Aspectoptima.
[31] McGill Software Engineering Laboratory (SEL).
Touchram.
http://www.cs.mcgill.ca/˜ joerg/SEL/TouchRAM.html, 2009.
[32] P. Tarr, H. Osser, W. Harrison, and S. M. Sutton JR. N degrees of separation: Multidimensional separation of concerns. In 21st Int’l Conf. Software
Engineering (ICSE), (Los Angeles)., (IEEE, 107 – 119), 1999.
[33] Gefei Zhang and Matthias Hölzl. HiLA: High-Level Asepcts for UML State
Machines. In Sudipto Ghosh, editor, Sel. Rev. Papers Wshs. at MoDELS’09, volume 6002 of Lect. Notes Comp. Sci., pages 104–118. Springer,
2010.
81