前言:
本文是模型转换领域的一篇Bible,被无数次的引用。几乎在所有的模型转换领域的论文中都会把它作为参考文献。作者在本文中第一次提出了用关系代数来定义模型转换的方法,开创了模型转换技术的一个流派。
本文中涉及的知识非常广泛,读懂本文需要以下知识:关系代数、集合论、UML、OCL以及MDA相关知识。特别是OCL,文中大量的使用了OCL来描述转换的约束和特性。我是第二次读这篇文章了,第一次因为不懂OCL,所以囫囵吞枣,不能领略其精华。建议所有研究MDA的同仁都读一下此文。
标题:
A Relational Approach to Defining Transformations in a Metamodel
地址:
暂无
时间:
2002以后
阅读时间:
第一次2004-10-27
第二次 2005-3-17
摘要:元建模正在成为定义类似UML等语言的标准方法。一个语言的定义分为三个部分:具体语法,抽象语法和语义域。使用元建模的方法有可能同时定义这三个方面,但是如何定义他们之间的转换还是不清晰的。本文提出了一种方法,它使用元建模模式,并抓住了“数学关系”的本质。它展示了这些模式如何被用来定义具体语法和抽象语法之间的“关系”,以及抽象语法和语义域的关系。这种方法的一个目标就是提供一种语言的完整规范,通过这种规范可以生成智能的工具。本方法符合其目标的程度也在本文中讨论了。
笔记:
1.给出了抽象语法,具体语法,语义域的元模型
元模型在本文中是以UML的子集以及OCL来表示的;
抽象语法:由package,class,Association,AssociationEnd组成,还定义了他们之间的约束,例如一个package中不能有重名的Class。
语义域:由snapshot,object,link,linkEnd组成,以及他们之间的约束;注意他们的约束要少一些,因为没有package的嵌套和class的继承等关系存在。
具体语法:由diagram,box,line,lineEnd组成,以及约束;注意box有两种,一种是haveTab(有一个小标签的)对应package和haveNoTab(没有小标签的)对应class。而且具体语法约束很少!
2.模型转换的模式
主要的灵感来自于关系代数。技术其实是很简单的:采用一种模式,它将“转换的关系”建模为一个二元关系或者一组二元关系,并将这种模型编码为对象模型。在这种思想下,“关系对”被建模为对象,而“关系”被映射成拥有一组“关系对”的对象。
关系对(Pairs):关系对由一个domain对象x(是Class X的对象),一个range对象(是Class Y的对象)和它们之间的连接对象(XY)组成。
关系(Relation):关系由一个domain集合(集合中都是Class X的对象),一个range集合(其中都是Class Y的对象),以及“关系对”对象的集合组成。
关系中定义了如下性质:
连接对象的x端都在domain集合中,连接对象的y端都在range集合中。
如果关系中有两个关系对e和f,其中e.x=f.x,e.y=f.y,那么e=f;(无冗余特性)
另外文中第6页对关系的性质进行了大量的定义,几乎把集合论中的一套班子都搬过来了,例如关系是“满射”还是“双射”等等。
相关的结构:
对关系进行了嵌套结构的转换关系定义。
3.模式的应用
抽象语法到语义域的转换定义:package对应snapshot;class对object;Association对link;AssociationEnd对linkEnd;另外还有很多约束条件。
约束条件中最复杂的两条:第一Association的势(cardinality)的上限和下限在link中保持了;第二,linkEnd所连接的object是属于linkEnd所对应的AssaciationEnd所连接的Class。
具体语法到抽象语法的转换:其中Box(hasTab)对应Package,box(not hasTab)对应Class,line对应Association,lineEnd对应AssocationEnd。
此外也有许多不同的约束条件。
4.结论
关于此方法的一些可能的进展:
将这种方法应用到更精密复杂的语言中;
将这种模式编码为包模板;
创造专用的符号来描述这些关系;
应用这项技术到MDA技术中;
自动化的生成或者配置工具;
和其他方法结合来更好的定义语言。
感想:
文中最复杂的一个约束是从抽象语法到语义域的转换定义中的一个约束:Association的势(cardinality)的上限和下限在link中保持了。它的具体含义是如果有Class A和B分别是AssociationA的两个AssociationEnd,其中B端具有势upper和lower,那么对于所有Snapshot中的对象a(A的实例)和b1,b2,bi…(B的实例),如果a和b1,b2,bi…之间有连接LinkA(AssociationA的实例),那么Class B的实例b1,b2,bi…的个数必须在upper和lower之间,否则就违反了约束。
作者用OCL描述了这个约束:
context PackageSnapshot inv:
package.association.associationEnd->forAll(ae |
snapshot.allObject()->select(o |
classRelObject.rangeLookup(o).class = {ae.source})
->forAll(o | let n = o.sourceOf->select(le |
associationRelLink.domainLookup(ae.owner).linkEnd
->includes(le))->size in n <= ae.upper and n >= ae.lower))
解释如下:
在PackageSnapshot这个“关系对”(Pair)中,必须满足一个不变式
对于package.association.associationEnd中的所有元素ae必须满足约束A。
约束A如下:
先取出snapshot中的所有对象,选择出满足条件B的对象o的集合,此集合必须满足约束C。
条件B如下:
rangeLookup(o)选择出了所有range为o的“关系对”,这些关系对是属于classRelObject关系的,然后找出这些关系对的class,如果class等于ae.source就将o选入集合。
约束C如下:
对于所有满足条件B的对象集合,其中每个对象o必须满足n<=ae.upper和n>=ae.lower,其中n的计算方法如下:
用o.sourceOf找出所有o所连接的LinkEnd,然后选择出满足条件D的le,组成一个集合,用size计算出这个集合的大小就是n的值。
条件D如下:
对于对象o的每个LinkEnd le,首先用domainLookup(ae.owner)找出所有“关系对”,这些关系对的左边是AssociationEnd(ae.owner),然后将关系对的右边(即linkEnd)全部取出来组成一个集合,如果此集合包含le,则le满足条件D。
我想如果这个约束可以看懂,那么看懂整篇文章就不难了。