Kent Model Transformation Language D.H.Akehurst, W.G.Howells, K.D.McDonald-Maier University of Kent at Canterbury
[email protected] Abstract. The Kent Model Transformation Language is the third generation of model transformation approaches developed at the University of Kent. In this paper we show a grammar for the language and illustrate its differences to the predecessors. The major difference of the latest approach is the inclusion of a Model Driven Development Environment for manipulating models and transformers as first class entities.
1 Introduction The Kent Model Transformation Language (KMTL) is the third generation in a series of transformation approaches developed at the University of Kent. The first was developed as part of Akehurst’s doctoral work [1], and in relation to a project Permabase [13] in which it was necessary to map UML based distributed system specifications onto a discrete event simulation engine. The transformation approach developed was a bi-directional, incremental and active technique; i.e. if the related models were defined to be ‘observable’, the transformation framework would react to local changes in one side of the model and update the other side accordingly. The approach has no pre-defined specification language and was based on a set of Java libraries including OCL support for defining activation constraints. Although successful for small transformations and used to support other projects (e.g. [7]), the lack of a specification language made it complex to use and the composition mechanism was not well defined. The second generation of transformers were built on top of the Kent Modelling Framework (KMF) tools and based on the more formal concept of Relations. Published in [5] and [6], this work looked specifically at providing well-defined structural patterns for modelling a traceable relationship between objects. The approach provided a basis to explore graphical specification languages for transformations [8] and has been used to support the DSE4DS research project [3, 4] (mapping distributed system specifications onto Timed Automata) and some Business Modelling work [12]. This transformation approach supported incremental (nonactive), bi-directional, declarative specifications with an option to use constructive parts in a specification where necessary. Although a successful approach with respect to the traceability structures, the technique lacked good tool support. A major limitation proved to be a lack of environment in which to manipulate models and model transformations. The third generation language, KMTL has been developed on the basis of experiences gained from the previous approaches. This language aims to be a declarative specification language, with the option to provide constructive parts if required. The semantics of the language draw from a formal foundation of relations
[OCL relations] and from ideas gleaned from submissions to the OMG’s QVT RFP [10]. The major advantage of this approach is the provision of a Model Driven Development Environment in which Models and Transformers may be manipulated as first class entities. In this paper we first introduce the MDD Environment, which is built on top of the Eclipse IDE [9]. Subsequently, we show an EBNF based grammar defining a text based concrete syntax for the language, which is also used to generate the language parser. Section 4 illustrates use of KMTL to specify a transformer for the compulsory example of the workshop and section 7 goes on to illustrate another example. The paper concludes with some discussion of future work and some observations on the work of this paper.
2 The KMF MDD Environment Before we can start writing transformations we need to understand the concepts of, and have an environment in which we are able to manipulate, Models, Transformations and their instances. We define them as follows:• Model: A model is a specification of types analogous to a database schema. Models can extend other models, i.e. include the type specifications of those other models. • Transformer: A transformer is a specification of how to map instances of types from one or more models into instances of types from another model or models. • Model Instance: a model instance is similar to a database; it is a specific collection of type instances (objects) whose types are defined within a specific model. • Transformer Instance: a transformer instance is a particular instantiation of a transformer, bound to a specific set of model instances. Models and Transformers are added to the environment as eclipse plug-ins. Use of the plug-in mechanism by the KMDDE is designed in such a manner as to facilitate incorporation of, models without specifying the implementation mechanism for the models, thus enabling us to plug-in 3rd party models (such as the org.w3c.dom XML library). We have been experimenting with a similar approach for transformer plugins, however currently transformers are required to implement a specific interface. Three constraints are imposed on models if they are to take advantage of the default XMI 2.0 serialisation support of our KMDDE: 1. all classes must define identifying properties (i.e. primary keys) 2. one of the classes must be designated a root classifier 3. all other classifiers must be composite parts of the root or one of its sub parts.
3 The Grammar The textual grammar for KMTL is an extension of an OCL based query language. We have developed a technique for specifying language grammars as an extension to the standard EBNF syntax that facilitates us to extend an existing grammar to create a new one. Although the details of this technique are not yet published; the following specification should be easy to follow.
The following partial grammar shows relevant rules from an OCL based expression or query language on which the transformation language is based: package kmf.kel; grammar expressions extends ... { pathName = NAME ('::' NAME)* ; literal = ... ; navigationExpression = ... ; expression = ... ; argumentList = expression (',' expression)* ; }
Table 1 extract from specification of query/expression language The grammar for our model transformation language is shown below; it is very similar to the proposed QVT [11] language. package kmf; grammar kmtl extends kmf.kel.expressions { ktlFile = [packageDefinition] transformer ; packageDefinition = 'package' pathName ';' ; transformer = 'transformer' NAME models '{' rule+ '}' ; rule = relation | mapping ; models = variableDeclaration (variableDeclaration)+ ; relation = 'relation' NAME domain+ [when]; mapping = 'mapping' NAME domain+ [when]; domain = variableDeclaration [propertyList] [body]; propertyList = '[' propertyDefList ']' ; propertyDefList = propertyDef (',' propertyDef)* ; propertyDef = navigationExpression '=' expression ; body = 'body' '{' expression '}'; when = 'when' '{' relExpression '}'; relExpression = NAME '(' argumentList ')' | relExpression 'and' relExpression | relExpression 'or' relExpression | '(' relExpression ')' ; }
Table 2 Grammar for Kent Model Transformation Language
4 The Compulsory Example The workshop CFP defines a compulsory example to be tackled; this example must map a simple model of classes onto a simple model of a relational database schema. The two models (from the CFP) are shown in Figure 1; a textual specification of the transformation given in the CFP.
Figure 1 Models for compulsory example The KMTL specification for this transformation is given in Table 3. It should be noted that the specification for the transformer is lossy, in the sense that the required output schema does not contain enough information from which to re-construct the input class model, thus most of the transformer rules are one-way mappings rather than bi-directional relations. transformer simpleModel_to_rdbms simpleModel : simpleModel dbModel : rdbms { mapping Class2Table cls:Class tbl:Table when { pClass2Table(cls, tbl) or npClass2Table(cls, tbl) } mapping pClass2Table cls:Class [is_persistent=true, name=n, allAttrs->select(a|a.is_primary)=prim] tbl:Table [name=n, pKey=pkey, fKeys=fkeys] when { Attribute2Column(cls.attrs, tbl.cols) and Attribute2Column(prim, pkey) and Attribute2Fkey(cls.allAttrs, fkeys) } mapping npClass2Table cls:Class [is_persistent=false, parent=parent ] tbl:Table [cols->select(c|true)=tcols, fkeys=fkeys] when { Class2Table(parent, tbl)
and Attribute2Columns(cls.attrs, tcols) and Attribute2FKey(cls.allAttrs, fkeys) } mapping Attribute2FKey att:Attribute [type.oclIsTypeOf(Class)=true] fKey:FKey [references=tbl, cols=cols] when { Class2Table(type.oclAsType(Class), tbl) and classAtt2Columns(att,cols) } mapping Association2TableEntry ass:Association [src=cls] tbl:Table [cols->select(c|true)=cols, fkeys->any(f|true)=fKey] when{ Class2Table(cls,tbl) and Association2Columns(ass, cols) and Association2FKey(ass,fKey) } mapping Association2FKey ass:Association [dst.is_persistent=true] fKey:FKey [references=tbl, cols=cols] when { Class2Table(ass.dst, tbl) and Association2Columns(ass,cols) } mapping Association2Columns ass:Association [name=n src.allAttrs->select(a|a.is_primary)=fAtts] cols:Set(Column) body { tcols->collect(c|Column{name=n+'_'+c.name, type=c.type}) } when { Attribute2Columns(fAtts, tcols) } relation Attribute2Columns att:Attribute cols:Set(Column) when { primativeAtt2Columns(att, cols) or classAtt2Columns(att, cols) }
mapping classAtt2Columns att:Attribute [type.oclIsTypeOf(Class)=true, type.attrs->select(a|a.is_primary)=fAtts, name=n] cols:Set(Column) body { tcols->collect(c|Column{name=n+'_'+c.name, type=c.type}) } when { Attribute2Columns(fAtts, tcols) } relation primativeAtt2Columns att:Attribute [type.oclIsTypeOf(PrimativeDataType)=true, type=t, name=n] cols:Set(Column) [cols->any(true).type=tn, cols->any(true).name=n] when { type2String(t,tn) } relation type2String type:PrimativeDataType [name=n] str:String [str=n] }
Table 3 KMTL specification for simpleModel-to-rdbms
Figure 2 Adaptation of Compulsory source and target models In order to implement this specification and support it in our MDD Environment, it is necessary to make a few changes to the source and target model specifications,
primarily to facilitate persistent storage of instances of those models. It should be noted that none of the additions are necessary for the specification of the transformer; they simply enable better support within our MDD Environment. The models of Figure 1 are adapted to those shown in Figure 2. The adaptations add a root classifier for each model (Package and Schema), add some compositions, and add some identifying properties. It is interesting to note that the transformer specification could be made simpler by adding some derived properties to the models and making some of the associations bidirectional. For example, a derived attribute allParents could simplify some of the aspects relating to super classes; and making the column-table association bidirectional would simplify the part of the specification that maps attributes and associations to columns; likewise for the Table-KFey associations.
5 The Semantics Our transformation specification is executed by mapping it to the Java programming language, i.e. a Java class is generated that will perform the specified transformation. There are at least two potential ways to execute a transformation: using an interpreter, executing the transformation expression directly; or by synthesising the transformation expression to an alternative language and executing the result. We prefer the latter approach as this gives us use of the debugging and other development tools of the target language to aid us in debugging/developing a transformation. Even though these are not specifically written for our language, it does save us building our own, at the cost of having to debug in the target language. Currently our semantics only handle binary transformers, i.e. a transformer that maps between two separate model instances; and we have only developed support for batch transformers not yet incorporating the traceability structures to support incremental and active implementations. The synthesis from KMTL to Java follows the following rules: • A transformer is mapped to a Java class • The model properties of the transformer are mapped to properties (getter methods) in the Java class. • Each relation is mapped to two different Java methods, which provide the mapping code for transforming in each direction. A mapping is mapped to a single method. • To facilitate recursive calls on relations, without running into infinite recursion issues, a trace of all relationships formed by a relation is stored for each method. This trace store is checked to see if an element has already been mapped, before executing the mapping code. • The source domain property definitions are used to determine if the relation can provide a valid mapping for the source object. • The target domain property definitions and the relation expressions in the when clause are used to build the target domain object. • The target and source domain objects are recorded in the trace store.
6 Another Example A simple example transformation that exhibits some non-trivial aspects is a mapping from a tree data structure to a graph is now presented. This example was addressed in [1], and we address it again here using the KMTL. It is one of the simplest, and yet not a trivial one-to-one example of a transformation that we have come across. The model specifications are shown in Figure 3, and the transformation in Table 4.
Figure 3 Tree and Graph Model Specifications transformer Tree_to_Graph treeModel : tree graphModel : graph { relation Tree2Graph tree:Tree [root=treeRoot] grph:Graph [vertex->any(v|v.incoming->isEmpty)=grphRoot] when { TNode2Vertex(treeRoot, grphRoot) } relation TNode2Vertex tnode:TNode [data=d, tree=t] vertex:Vertex [data=d, graph=g] when { Tree2Graph(t,g) and child2Edge(tnode.children, vertex.outgoing) and child2Edge(tnode, vertex.incoming) } relation child2Edge child:TNode [parent=p, tree=t] edge:Edge [source=src, dest=dst, graph=g] when {
Tree2Graph(t,g) and TNode2Vertex(p, src) and TNode2Vertex(child, dst) } }
Table 4 KMTL specification for tree-to-graph There is naturally more than one way to specify this transformer, even using the same language, and we have illustrated one particular specification. The interesting issues about this transformation are: Reliance on the bi-direction associations: The specification relies on the bidirectional nature of, in particular, the associations Graph-Vertex, Graph-Edge and Tree-TNode in order to correctly link up Vertices and Edges with their owning Graph. Without the bi-directional associations, the transformer specification would change significantly. Mapping graph Edges to pairs of TNodes: This illustrates the need to map a single object from one model onto an association (link) between objects in the other. There are a number of other ways in which this could be specified; ideally we would like to specify a relation that maps an edge to a pair of TNodes, e.g. Table 5; however our synthesis semantics does not currently cope with this; the mapping from the pair to edge would work fine, but not the reverse. relation pair2Edge pair:Tuple(parent:TNode, child:TNode) edge:Edge when { TNode2Vertex(parent, edge.source) and TNode2Vertex(child, edge.dest) }
Table 5 Mapping the root of the tree: to an appropriate vertex in a bi-directional manner. The expression we use to identify the root of the tree, illustrates a complex part of the semantics. In the graph->tree direction, the following code applies: Vertex grphRoot = null; for(Vertex v: grph.getVertex()) // \ if (v.getIncoming().isEmpty()) { // \ grphRoot = v; // ->any(v|v...) break; // / } // / TNode treeRoot = TNode2Vertex(grphRoot); tree.setRoot(treeRoot);
However, in the reverse direction, it is necessary to assign a value to the java version of an ‘any’ expression, i.e. grph.vertex->any(v|…) := treeRoot. To handle this
we could provide a ‘body’ expression that constructs the tree; however, it is possible to provide a valid semantics to an assignment to the ‘any’ expression – by adding the assigned value to the source of the ‘any’, e.g. TNode treeRoot = tree.getRoot(); Vertex grphRoot = TNode2Graph(treeRoot); grph.getVertex().add(grphRoot); // vertex->any(...) := grphRoot
7 Conclusion and Future Work The current implementation of our KMTL is fairly basic and we intend to implement the traceability structures of [6] and the active and incremental aspects of [1] to the Java synthesis process. Another possibility is to provide support in alternative languages, such as C#. Other planned future work is to improve the tool support for specification of transformers, providing better error feed back and a fully featured eclipse editor. In addition to increasing the usability of the current KMTL, it currently lacks a good technique for defining the properties of a relation e.g. bi-jection, sur-jection, total, partial etc and these may be provided in due course. These issues are discussed in [2]. Although our KMTL is very similar (and in part draws from) the QVT submission [11] we feel that our syntax is easier to read. In addition, we tackle some of the difficult issues in a different manner, for instance use of the select and any operations as part of property definitions (e.g. in the Tree2Graph relation or the pClass2Table mapping) requires a reverse semantics for those operations in order to use them as part of the mechanism for correctly constructing domain objects. The QVT submission uses an alternative ‘collection pattern’ concept instead; it would be interesting to investigate which approach is the more expressive. A major lesson we have learnt from the many years of specifying transformers, using a variety of techniques, is that whatever transformer specification technique or language is used, the complexity of the transformer is greatly influenced by the specification of the source and target models. In particular, the use of bi-directional associations generally simplifies a transformer as the links can be navigated in either direction; and in general ‘good’ specification of the source an target models greatly aids specification of a transformer, e.g. specification of appropriate identifying properties (primary keys) on classes. Some difficult issues we are currently addressing with respect to our KMDDE are: • Transformers to Any model, e.g. providing a transformer which has one of its model variables as a wildcard. Useful for transformers such as one that maps Any model instance to an XMI representation. • Relations or Mappings in which it is not obvious which domain variable refers to objects from which model. e.g. when the transformer source and target model instances are of the same type. This paper has been cut down from a longer, unpublished, document which includes more details on the semantics of the KMTL and the Java synthesis process, additional examples and more extensive comparison to other approaches. The extracts included in this workshop paper are intended to illustrate specific details of our approach and its background.
References [1]
[2]
[3]
[4]
[5]
[6]
[7] [8]
[9] [10] [11]
[12]
[13]
Akehurst D. H., "Model Translation: A UML-based specification technique and active implementation approach," thesis, Department of Computing, University of Kent at Canterbury, Canterbury, 2000 Akehurst D. H., "Relations in OCL," in proceedings UML Workshop: OCL and Model Driven Engineering, Lisbon, Portugal, October 2004. Akehurst D. H., Derrick J., and Waters A. G., "Addressing Computational Viewpoint Design," in proceedings Enterprise Distributed Object Computing Conference, EDOC 2003, Brisbane, Australia, pp. 147, September 2003. Akehurst D. H., Derrick J., and Waters A. G., "Design and Verification of Distributed Multi-media Systems," in E. Najm, U. Nestmann, and P. Stevens (eds) proceedings Formal Methods for Open Object-Based Distributed Systems, FMOODS 2003, Paris, pp. 276-292, November 2003. Akehurst D. H. and Kent S., "A Relational Approach to Defining Transformations in a Metamodel," in J.-M. Jézéquel, H. Hussmann, and S. Cook (eds) proceedings The Unified Modeling Language 5th International Conference, LNCS, Springer, 2460, Dresden, Germany, pp. 305-320, 2002. Akehurst D. H., Kent S., and Patrascoiu O., "A relational approach to defining and implementing transformations between metamodels," Journal on Software and Systems Modeling, vol. 2, pp. 215, November 2003. Bowman H., Bryans J., and Derrick J., "Analysis of a Multimedia Stream using Stochastic Process Algebra," The Computer Journal, vol. 44, 2001. Hausmann J. H. and Kent S., "Visualizing model mappings in UML," in proceedings ACM Symposium on Software Visualization 2003, San Diego, USA, June 2003. IBM, "Eclipse Universal Tool Platform," 2001, http:/www.eclipse.org OMG, "Request for Proposal: MOF 2.0 Query / Views / Transformations RFP," Object Management Group, ad/2002-04-10, April 2002. OMG, "Revised submission for MOF 2.0 Query / Views / Transformations RFP (ad/2002-04-10), QVT-Merge Group, Version 1.0," Object Management Group, April 2004. Steen M. W. A., Doest H. L. t., Lankhorst M. M., and Akehurst D. H., "Supporting Viewpoint-Oriented Enterprise Architecture," in proceedings EDOC 2004, submitted. Waters A. G., Linington P. F., Akehurst D. H., Utton P., and Martin G., "Permabase: Predicting the performance of distributed systems at the design stage," IEE Proceedings - Software, vol. 148, pp. 113-121, August 2001.