前言:
本文是模型轉換領域的一篇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。
我想如果這個約束可以看懂,那么看懂整篇文章就不難了。