=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== https://ceur-ws.org/Vol-1305/paper12.pdf
    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
             src = " transformations / java / ToJava . egl " >
        < model ref = " classes " as = " Model " / >
        < parameter name = " tgtdir " value = " ${ generate - tgt }/ java / " / >
        < parameter name = " pck " value = " ${ tgtsubdir }. java " / >
     

     < epsilon . eglMerge >
        < file >
           < include name = " ${ generate - tgt }/ java /*. java " / >

         < superimpose artifactHandler = " java15 " / >
      
   


...




                           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