=Paper=
{{Paper
|id=Vol-1305/paper12
|storemode=property
|title=Aspectual Code Generators for Easy Generation of FIXML to OO Mappings
|pdfUrl=https://ceur-ws.org/Vol-1305/paper12.pdf
|volume=Vol-1305
|dblpUrl=https://dblp.org/rec/conf/staf/ZschalerT14
}}
==Aspectual Code Generators for Easy Generation of FIXML to OO Mappings==
Mapping FIXML to OO with Aspectual Code Generators
Steffen Zschaler, Sobhan Yassipour Tehrani
Department of Informatics, King’s College London
szschaler@acm.org, sobhan.yassipour tehrani@kcl.ac.uk
This paper provides a solution to the TTC 2014 FIXML study case. The case requires the imple-
mentation of a straightforward mapping from XML messages in the FIXML format to a set of source
files implementing the schema of such a message and, optionally, an instantiation with the data from
the message. There is a requirement for producing code in a range of programming languages.
The biggest challenge for transformation design in this study case is that the same tag may occur
in multiple places in the FIXML message, but with a different set of attributes. The generator must
merge all of these occurrences into a single representation in the generated code. We demonstrate
how the use of symmetric, language-aware code generators relieves the transformation developer
almost entirely from considering this requirement. As a result, the transformation specifications we
have written are extremely straightforward and simple. We present generation to Java and C#.
1 Introduction
FIXML is a language used in the financial sector to express financial-transaction information for machine-
to-machine communication in electronic trading. Object-oriented wrappers are convenient for use in
end-point systems when reading, constructing, and manipulating FIXML messages. It is possible to
introduce new and custom formats for messages; this happens frequently.
The study case asks for implementations of code generators that produce wrapper classes given
a specific FIXML message. There are, thus, two parts to the problem posed: 1) to extract the message
schema and 2) to generate class code implementing this schema. The case description does, consequently,
ask for the solution to be broken down into two major phases (with an initialisation phase for reading the
XML document): 1) extracting the schema into an instance of a programming-language meta-model and
2) generation of source code from the model thus created.
The code-generation phase is almost trivial to implement as it effectively amounts to a textbook case
of class-diagram to class-skeleton generation. Schema extraction is a little bit more interesting in that it
requires the merging of information from different parts of the XML document: Tags of the same name
can occur in different places of the document, but with a different set of attributes and sub-nodes.
In our implementation, there are two design decisions that are worth noting:
1. We use symmetric language-aware aspects [6, 7] in the implementation of our code-generation
templates, obviating almost completely the need for any special consideration of the need for
merging in schema extraction; and
2. We use a completely target-language independent meta-model of classes and attributes (i.e., of the
schema). In fact, because of our use of symmetric aspects, our meta-model does not need to insist
on uniqueness of class names and becomes an object model of the FIXML message rather than the
extracted schema only. This enables us to easily generate a test method instantiating our generated
classes with exactly the data from the given FIXML message.
Our implementation is based on Epsilon [2–5] extended with symmetric-aspect support [6, 7].
Submitted to:
c S. Zschaler & S. Y. Tehrani
TTC 2014
2 Mapping FIXML to OO with Aspectual Code Generators
Code
CG Template 1 Slice
CG Template 2 Registry Code Slice Weaver Output Files
...
CG Template n
Save to file
Generate Weave
Registry empty Text registered for file Text woven
Generate
Register
Figure 1: Infrastructure for symmetric, language-aware aspects for code-generation (from [6])
2 Symmetric Aspects for Code Generation
In [6,7], we have introduced symmetric, language-aware aspects for code-generation templates to enable
advanced modularity for code-generation templates. Detailed descriptions are in these papers, but we
give a brief summary here to simplify understanding of our solution to the TTC 2014 FIXML case.
Figure 1 shows an overview of the infrastructure for code generation with symmetric aspects. Cru-
cially, results from the interpretation of code-generation templates are not directly written to a file, but
are centrally registered against the name of the file they are meant to produce. Later, all texts registered
against the same file name are merged before they are finally written to disk.
For the merging step, we use an implementation of superimposition; specifically, F EATURE H OUSE
[1]. F EATURE H OUSE comes with our implementation by default, but other merging strategies can be
implemented and provided. F EATURE H OUSE merges two texts in two steps: First, the texts are parsed
using a coarse-grained grammar for the particular language they are written in. The aim is to extract
named entities in the code; details of the implementation (e.g., method bodies) are kept as opaque blocks
of code. Two such feature-structure trees are then combined by merging the contents of nodes of the
same name. Where these contents are opaque blocks, F EATURE H OUSE calls out to language-specific
semantic merge operators. For example, two Java method bodies are merged by inserting the second in
any place where the first mentions the special invocation of ‘origin()’.
As a result, more than one code-generation template can contribute to a given file. If each template
is written to be computationally complete, they can be swapped in or out of a transformation workflow
completely independently of each other, giving great flexibility for transformation reuse, but also for
debugging. Because the templates are standard generation templates (written in EGL [5] in our case),
they can alternatively also be run by the standard EGL engine and the result written to disk directly,
making it accessible for debugging.
Symmetric language-aware aspects for code generation have been implemented as an extension to
EGL and are available from EpsilonLabs.1
1 EpsilonLabs is available at http://epsilonlabs.googlecode.com/. The update site for the symmetric as-
pects for code-generation plugins is http://epsilonlabs.googlecode.com/svn/trunk/org.eclipse.epsilon.egl.
symmetric_ao.updatesite.
S. Zschaler & S. Y. Tehrani 3
LoadXML XMLToClass ClassToJava
XML : EOL
XML Model : ETL
Class Model : EGLSym-AO-CG
Code : Java
<>
<>
XML MetaModel : Ecore
Class MetaModel : Ecore
Figure 2: Transformation architecture. Boxes correspond to artefacts (with their language expressed after
a colon or using an <> relation) and arrows describe transformations
3 Solution
We first describe the complete solution for generating Java code, before discussing the changes needed
for generating C# code.
3.1 Transformation to Java
Figure 2 gives an overview of the complete transformation architecture implemented for generating Java
code from FIXML messages. In a first step, the XML is parsed and translated into an instance of the
XML metamodel defined by the task specification. This model is then translated into a model of classes
and attributes, before code is finally generated. In the following, we will discuss each of these steps in
some more detail.
3.1.1 LoadXML
The case specification provided a meta-model for XML documents and to be used as an intermediary
storage format for the FIXML message to be processed. We have encoded the given meta-model in Ecore
and have written a simple EOL [2] program to parse XML documents into instances of this meta-model.
This is simplified by the fact that Epsilon already comes with an XML parser, called a model driver,
exposing the contents of an XML file to model-management operations through a naming convention [4].
The complete EOL program for LoadXML can be found in Listing 1.
3.1.2 XMLToClass
As a next step, we need to extract the message schema from the concrete message given. In our imple-
mentation, this amounts to a very straightforward copying of the XML model into a model of classes and
their attributes, differentiating between string-typed and class-typed attributes.2 The resulting model does
not describe a schema, but represents the object structure of the message given. The only change made
at this step is for the transformation to ensure that attribute names are unique within an object (although
not necessarily between different objects of the same class). This will work together with name-based
merging to ensure generation of minimal code. Additionally, we also keep track of the top-level element
in the object structure.
This transformation is written in ETL [3] and produces instances of the meta-model shown in Fig. 3.
The code of the transformation is shown in Listings 2 and 3.
2 Here we would also do any type analysis if we were providing a solution for that additional requirement.
4 Mapping FIXML to OO with Aspectual Code Generators
Model
1 topClass Attribute
*
DataType Class name : String
attributes
value : String
Type type
name : String 1
Figure 3: Class meta-model diagram
Note that the transformation does not merge different occurrences of the a tag of the same name into
one class definition in the class model. As a result, the model produced may contain multiple classes of
the same name. Their definitions will be merged automatically once code has been generated.
3.1.3 ClassToJava
The final step of the transformation chain produces Java code from the class model. The template is
written in EGL and is extremely straightforward. It consists of a controller template (cf. Listing 4) that
instantiates a second template for every class in the model. That second template (cf. Listing 5) simply
generates a class skeleton including all attributes and references as well as a default constructor and a
constructor for the attributes and references found.
Note that the name of the file to generate is derived from the name of the class in Listing 4. This
may lead to multiple versions of the same file being generated. However, the build workflow shown in
Listing 6 invokes the template using eglRegister rather than egl, thus registering all generated code
in the central registry. Only the call to eglMerge combines all code produced for a particular class.
Because elements of the same name are unified in the merging process, the requirement of the study case
is implicitly satisfied.
Our code-generation platform is highly customisable. We have implemented a custom merge strategy
for attributes in Java code which can merge occurrences of an attribute of type X with occurrences of an
attribute of the same name of type List. This has enabled us to support the generation of collection-
typed attributes where multiple attributes / children of the same name are used in a FIXML message.
We also show a modular definition of an additional feature, namely the generation of a main method
instantiating the new classes with data from the FIXML message from which they were generated. To
this end, we defined two separate code-generation templates: the first (cf. Listing 7) is a controller
template identifying the top class in a given class model and invoking the second template for this class.
The second template (cf. Listing 8) then generates an empty class body with only a main method with
a recursively constructed constructor call in it. Note that because of a limitation in Java we are not
generating custom constructors when there are more than 200 attributes in a class. This is to avoid
compilation errors, because there is a maximum number of parameters that can be passed to a constructor.
3.2 Transformation to C#
C# and Java are quite similar programming languages. The syntax of both languages is based on C/C++.
They are both object-oriented and strongly typed languages. In general, the overall structure of C# and
S. Zschaler & S. Y. Tehrani 5
Java are almost identical for this FIXML transformation. The only real difference is the need to use
‘using System;’ at the beginning of each file to allow for the use of upper-case ‘String’ as a type name.
Because neither the class model nor the XML model contain any information specific to the target
language, the early transformations can be kept unchanged. Only the final code-generation needs to be
adjusted by 1) using the C#-specific template and 2) changing the language handler for the invocation
of eglMerge to csharp. Language handlers encapsulate language-specific information like the feature-
structure grammar and semantic merge-operators for unparsed blocks. A C# language handler did not
exist in the original version of symmetric aspects for code generation as presented in [6, 7]. However,
as the architectures of the generation infrastructure and the underlying F EATURE H OUSE system are
designed to be extensible, adding one was a matter of a few minutes.
4 Conclusions and Outlook
We have presented a solution to the TTC 2014 FIXML case using symmetric aspects for code generation.
The key feature of our solution is that our implementation could be largely built language independently
and with almost no concern for schema derivation issues. We have not implemented the generator for
C++. However, this could be easily realised following the same ideas by adding an appropriate set of
code-generator templates.
Tables 1 and 2 show the results for the various metrics requested in the case specification.
References
[1] Sven Apel, Christian Kästner & Christian Lengauer (2009): F EATURE H OUSE: Language-Independent, Auto-
mated Software Composition. In Stephen Fickas, Joanne Atlee & Paola Inverardi, editors: Proc. 31st Int’l Conf.
on Software Engineering (ICSE’09), IEEE Computer Society, pp. 221–231, doi:10.1109/ICSE.2009.5070523.
[2] Dimitrios S. Kolovos, Richard F. Paige & Fiona Polack (2006): The Epsilon Object Language (EOL).
In Arend Rensink & Jos Warmer, editors: Proc. ECMDA-FA 2006, LNCS 4066, Springer, pp. 128–142,
doi:10.1007/11787044 11.
[3] Dimitrios S. Kolovos, Richard F. Paige & Fiona A.C. Polack (2008): The Epsilon Transformation Language.
In Antonio Vallecillo, Jeff Gray & Alfonso Pierantonio, editors: Proc. 1st Int’l. Conf. on Theory and Practice
of Model Transformations (ICMT’08), Lecture Notes in Computer Science 5063, Springer-Verlag.
[4] Dimitrios S. Kolovos, Louis M. Rose, James Williams, Nicholas Matragkas & Richard F. Paige (2012): A
Lightweight Approach for Managing XML Documents with MDE Languages. In Antonio Vallecillo, Juha-
Pekka Tolvanen, Ekkart Kindler, Harald Störrle & Dimitris Kolovos, editors: Proc. 8th European Conf. on
Modelling Foundations and Applications (ECMFA’12), LNCS 7349, Springer, pp. 118–132, doi:10.1007/978-
3-642-31491-9 11. Available at http://dx.doi.org/10.1007/978-3-642-31491-9_11.
[5] Louis M. Rose, Richard F. Paige, Dimitrios S. Kolovos & Fiona A. Polack (2008): The Epsilon Generation
Language. In Ina Schieferdecker & Alan Hartman, editors: Proc. 4th European Conf. on Model Driven
Architecture (ECMDA-FA’08), Springer, pp. 1–16, doi:10.1007/978-3-540-69100-6 1.
[6] Steffen Zschaler & Awais Rashid (2011): Symmetric Language-Aware Aspects for Modular Code Generators.
Technical Report TR-11-01, King’s College London, Department of Informatics.
[7] Steffen Zschaler & Awais Rashid (2011): Towards Modular Code Generators Using Symmetric Language-
Aware Aspects. In: Proceedings of the 1st International Workshop on Free Composition, FREECO ’11, ACM,
New York, NY, USA, pp. 6:1–6:5, doi:10.1145/2068776.2068782. Available at http://doi.acm.org/10.
1145/2068776.2068782.
6 Mapping FIXML to OO with Aspectual Code Generators
A Transformation Implementation Examples
Listing 1: LoadXML implementation in EOL
generateFor ( XMLDoc . root );
operation generateFor ( e : Element ) : XML ! XMLNode {
var node : XML ! XMLNode = new XML ! XMLNode ;
node . tag = e . tagName ;
if ( e . getAttributes (). length > 0) {
for ( idx in Sequence {1.. e . getAttributes (). length }) {
var attr = e . getAttributes (). item ( idx - 1);
var xmlAttr : XML ! XMLAttribute = new XML ! XMLAttribute ;
node . attributes = node . attributes - > including ( xmlAttr );
xmlAttr . name = attr . nodeName ;
xmlAttr . value = attr . nodeValue ;
}
}
for ( elt in e . children ) {
node . subnodes = node . subnodes
-> including ( generateFor ( elt ));
}
return node ;
}
S. Zschaler & S. Y. Tehrani 7
Listing 2: XMLtoClass implementation in ETL
pre {
var STRING_TYPE : Classes ! DataType = new Classes ! DataType ;
STRING_TYPE . name = " String " ;
}
rule NodeToClass
transform s : XML ! XMLNode
to t : Classes ! Class {
t . name = s . tag ;
var uniqueID = new Map ;
for ( attr in s . attributes ) {
var newAttr = attr . equivalent ();
newAttr . name = newAttr . name . getUniqueVersion ( uniqueID );
t . attributes = t . attributes - > including ( newAttr );
}
for ( elt in s . subnodes ) {
var attr : Classes ! Attribute = new Classes ! Attribute ;
t . attributes = t . attributes - > including ( attr );
attr . name = elt . tag . getUniqueVersion ( uniqueID );
attr . type ::= elt ;
}
}
rule AttrToAttr
transform s : XML ! XMLAttribute
to t : Classes ! Attribute {
t . name = s . name ;
t . value = s . value ;
t . type = STRING_TYPE ;
}
post {
var mdl : Classes ! Model = new Classes ! Model ;
mdl . topClass ::= getTopNode ();
}
8 Mapping FIXML to OO with Aspectual Code Generators
Listing 3: XMLtoClass implementation in ETL (ctd.)
operation getTopNode () : XML ! XMLNode {
var resultSet = XML ! XMLNode . all ;
for ( node in XML ! XMLNode . all ) {
resultSet = resultSet - > excludingAll ( node . subnodes );
}
return resultSet . random ();
}
operation String getUniqueVersion ( uniqueID ) : String {
var result : Integer = 0;
if ( uniqueID . containsKey ( self )) {
result = uniqueID . get ( self );
uniqueID . put ( self , result + 1);
}
else {
uniqueID . put ( self , 1);
}
return self + result ;
}
Listing 4: ClassToJava controller template
[%
for ( cl in Model ! Class . all ()) {
var t := TemplateFactory . load ( ’ JavaOneClass . egl ’ );
t . populate ( ’ currentClass ’ , cl );
t . generate ( tgtdir + cl . name + ’. java ’ );
}
%]
S. Zschaler & S. Y. Tehrani 9
Listing 5: ClassToJava per-class template
package [%= pck %];
public class [%= currentClass . name %] {
[%
for ( prop : Model ! Attribute in currentClass . attributes ) {
%]
private [%= prop . type . name %] [%= prop . name %] =
[% if ( prop . type . isKindOf ( Model ! DataType )) {
%] " [%= prop . value %] " [%
} else {
%] new [%= prop . type . name %] ()[%}%];
[%
}
%]
public [%= currentClass . name %]() {}
[% if (( not currentClass . attributes - > isEmpty ()) and
// Java is not happy with too many parameters
( currentClass . attributes - > size () <= 200)) {%]
public [%= currentClass . name %]([%
var first = true ;
for ( prop : Model ! Attribute in currentClass . attributes ) {
if ( not first ) {%] , [%}
else { first = false ;}
%][%= prop . type . name %] [%= prop . name %][%
}%]) {
[%
for ( prop : Model ! Attribute in
currentClass . attributes ) {
%] this .[%= prop . name %] = [%= prop . name %];
[%}%]
}
[%}%]
}
10 Mapping FIXML to OO with Aspectual Code Generators
Listing 6: Build workflow
...
< target name = " generate - java " depends = " generate - general " >
< epsilon . eglRegister
src = " transformations / java / GenerateMain . egl " >
< model ref = " classes " as = " Model " / >
< parameter name = " tgtdir " value = " ${ generate - tgt }/ java / " / >
< parameter name = " pck " value = " ${ tgtsubdir }. java " / >
epsilon . eglRegister >
< epsilon . eglRegister
src = " transformations / java / ToJava . egl " >
< model ref = " classes " as = " Model " / >
< parameter name = " tgtdir " value = " ${ generate - tgt }/ java / " / >
< parameter name = " pck " value = " ${ tgtsubdir }. java " / >
epsilon . eglRegister >
< epsilon . eglMerge >
< file >
< include name = " ${ generate - tgt }/ java /*. java " / >
< superimpose artifactHandler = " java15 " / >
file >
epsilon . eglMerge >
target >
...
Listing 7: Java main method controller template
[%
for ( mdl in Model ! Model ) {
var t := TemplateFactory . load ( ’ JavaMainMethod . egl ’ );
t . populate ( ’ currentClass ’ , mdl . topClass );
t . generate ( tgtdir + mdl . topClass . name + ’. java ’ );
}
%]
S. Zschaler & S. Y. Tehrani 11
Listing 8: Java main method template
package [%= pck %];
public class [%= currentClass . name %] {
public static void main ( String [] args ) {
[%= currentClass . name %] top
= [%= currentClass . g e n e r a t e C o n s t r u c t o r C a l l ()%];
}
}
[%
operation Model ! Class g e n e r a t e C o n s t r u c t o r C a l l () : String {
var result : String = " new " + self . name + " ( " ;
// Java doesn ’t like too many parameters
if ( self . attributes - > size () <= 200) {
var first = true ;
for ( attr in self . attributes ) {
if ( not first ) {
result = result + " , " ;
}
else {
first = false ;
}
if ( attr . type . isKindOf ( Model ! DataType )) {
result = result + ’" ’ + attr . value + ’" ’;
}
else {
result = result +
attr . type . g e n e r a t e C o n s t r u c t o r C a l l ();
}
}
}
result = result + " ) " ;
return result ;
}
%]
12 Mapping FIXML to OO with Aspectual Code Generators
B Metrics
Complexity It is not entirely clear what is meant by an operator or
an entity/feature reference in this context, so the below
values are approximations:
LoadXML – 35
XMLToClass – 61
ClassToJava – 12 (controller template) + 34 (per-
class template) + 11 (main-method controller
template) + 29 (main-method generation) = 86
ClassToCS – 12 (controller template) + 31 (per-class
template) + 11 (main-method controller tem-
plate) + 26 (main-method generation) = 80
Execution time The following times (in milliseconds) were
measured when running all test cases on
a TravelMate laptop with i5 CPU run-
ning at 2.4GHz and 4GB of main memory.
Stage Minimum Average Maximum
LoadXML 78 299 1062
XMLToClass 31 304 1451
ClassToCSharp 63 1929 7317
ClassToJava 218 1713 5647
It should be noted that the times shown can vary sub-
stantially between runs of the experiment set. The
code-generation stage takes the most time, which is
in line with the fact that the main processing happens
here. Further breakdown of the timing for Java gener-
ation reveals the following for the same run as above:
Stage Minimum Average Maximum
RegisterJava 109 819 2636
MergeJava 109 894 3011
Abstraction level Medium as this is a declarative-imperative solution.
Table 1: Metrics
S. Zschaler & S. Y. Tehrani 13
Accuracy Syntactic correctness (cf. Table 3) and semantic
preservation are achieved. Uniqueness of attribute
names is guaranteed by XMLToClass.
Development effort Approx. 3.5 person hours for Java; approx. 0.5 addi-
tional person hours for C#; approx. 1 person hour for
a generalised build script (optional).
Fault tolerance High – the transformation accurately reports errors in
the XML files.
Modularity Below are approximate values making assumptions
about the meaning of ’rule’:
LoadXML – 1 − 1/1 = 0
XMLToClass – 1 − 5/6 = 1/6
ClassToJava – 1 − 3/4 = 1/4
ClassToCS – 1 − 3/4 = 1/4
Table 2: Metrics (ctd.)
TestCase 3: [epsilon.xml.loadModel] [Fatal Error]
test3.xml:25:3: The element type "Order"
must be terminated by the matching end-tag
"".
TestCase 7: [epsilon.xml.loadModel] [Fatal Error]
test7.xml:14:12: The element type "Sndr"
must be terminated by the matching end-tag
"".
TestCase 8: [epsilon.xml.loadModel] [Fatal Error]
test8.xml:19:10: The element type "Hdr"
must be terminated by the matching end-tag
"".
Table 3: Error messages