第二章 文獻探討
2.4 QVT 基本語法
2.4.5 集合類型
QVT的轉換規則經常會作用在同一類型的元素上,例如類別圖中的類別元素 一併適用某一轉換規則。QVT因此提供集合運算函數方便開發人員進行集合運 算,其相關函數如表9。
表9. 集合表達類型
型態 描述說明
Set() 表示在集合中沒有重複的元素
Sequence() 表示是Bag,但元素有次序性
Bag() 表示在集合中可以存在重複的元素
OrderedSet() 表示是Set,但元素有次序性 2.5 QVT 轉換語法
本研究使用QVT-O將來源模型轉換至目標模型,以下介紹轉換相關語法。
2.5.1 main 程序
QVT程式進入點由main程序開始執行,main程序包含輸入(來源模型)與輸出 參數(目標模型)。圖9是main程序的撰寫語法,括弧內的in表示後面的model是來 源模型,A是來源模型的Meta-Mode,B是目標模型的Meta-Model。
mapping main(in model: A): B {
mapping main(in model: A): B {
進入點來源模型之
行定義,例如定義目標模型名稱或是將其元素呼叫其他轉換函數(如圖11)。
mapping A::A2B() : B{
init{
name := 'A2BModel';
propOfB += d.C2D();
}
mapping A::A2B() : B{
init{
name := 'A2BModel';
propOfB += d.C2D();
}
result := create(propOfA1,propOfA2);
result.propOfB += self.propOfA3.C2D();
}
result := create(propOfA1,propOfA2);
result.propOfB += self.propOfA3.C2D();
}
可以進行條件判斷以決定轉換方式。其運作是將一個或多個來源傳入值後,經由
query change(in name : String) : String{
if name = 'A' then 'B' else
query change(in name : String) : String{
if name = 'A' then 'B' else
法與其呼叫之query判斷函數,在參考Meta-Model定義來源模型(A)與目標模型(B) 後,加上when子句可以對來源模型加以限制,當when子句中所呼叫的query函數 回傳值為false時,後面所定義的轉換操作將不會執行,並且回傳空值。
mapping A::A2B() : B when{self.hasClasses()}
{...}
query A::hasClasses() : Boolean {
name ='Customer_Data' or name='Order_Data' or name='Bag_Data' or name='Lunch_Data';
} mapping A::A2B() : B when{self.hasClasses()}
{...}
query A::hasClasses() : Boolean {
name ='Customer_Data' or name='Order_Data' or name='Bag_Data' or name='Lunch_Data';
}
2.6.3 resolve 新增語法
result := self.resolve(B)-> any(true);
} object {
name := self.name;
}
result := self.resolve(B)-> any(true);
} object {
name := self.name;
}
metamodel 'http://www.borland.com/together/erPhysical';
metamodel 'http://www.borland.com/together/uml';
metamodel 'http://www.borland.com/together/uml20';
mapping main(in model: uml::together::Model): erPhysical::Model { schemas +=
model.allInstances(uml::kernel::packages::Package).toSchema();
}
mapping
uml::kernel::packages::Package::toSchema() : erPhysical::Schema{
init {
var classes :=
self.ownedMembers.oclAsType(uml20::classes::Class);
}
name := self.name;
visibility := self.visibility;
entities += classes.toEntityInitial();
}
mapping
uml20::classes::Class::toEntityInitial() :erPhysical::Entity { init {
result :=
self.resolve(erPhysical::Entity)->any(true);
} object {
name := self.name;
}
mapping main(in model: uml::together::Model): erPhysical::Model { schemas +=
model.allInstances(uml::kernel::packages::Package).toSchema();
}
mapping
uml::kernel::packages::Package::toSchema() : erPhysical::Schema{
init {
var classes :=
self.ownedMembers.oclAsType(uml20::classes::Class);
}
name := self.name;
visibility := self.visibility;
entities += classes.toEntityInitial();
}
mapping
uml20::classes::Class::toEntityInitial() :erPhysical::Entity { init {
result :=
self.resolve(erPhysical::Entity)->any(true);
} object {
name := self.name;
}
2.7.1 Meta-Model 的定義
MDA轉換是在MOF的架構下執行,程式碼必須先定義來源模型與目標模型 的Meta-Model(M2層)。以Borland Together軟體平台為例,程式碼先匯入三個 Borland Together所提供的Meta-Model(erPhysical、uml、uml20)(圖17),QVT 程式才能依據Meta-Model進行轉換。
metamodel 'http://www.borland.com/together/erPhysical';
metamodel 'http://www.borland.com/together/uml';
metamodel 'http://www.borland.com/together/uml20';
圖17. Borland Together 軟體平台中 Meta-Model 的定義
2.7.2 轉換進入點
程式轉換以main程序為起點(如圖18),並在main程序中輸入來源模型之 Meta-Model 參 數 , 該 範 例 為 uml::together::Model ; 並 定 義 輸 出 目 標 模 型 之 Meta-Model參數,該範例為erPhysical::Model,main程序主體叫toSchema函數進 行來源模型的轉換。
mapping main(in model: uml::together::Model): erPhysical::Model { schemas +=
model.allInstances(uml::kernel::packages::Package).toSchema();
}
圖18. 轉換進入點 main 程序
2.7.3 toSchema 函數
toSchema 函 數 中 首 先 定 義 了 來 源 模 型 之 Meta-Model 參 數
( uml::kernel::packages::Package ) 與 輸 出 目 標 模 型 之 Meta-Model 參 數
(erPhysical::Schema)(圖19), init部分透過oclAsType(uml20::classes::Class)將 ownedMembers裡的圖形鎖定在類別圖,並存放至classes變數中,以便在object部 分呼叫函數進行轉換。object部分則是定義轉換目標模型erPhysical::Schema中的 name與visibility,以及將init部分所新增的classes變數呼叫toEntityInitial函數進行 轉換並存放至entities中。
mapping
uml::kernel::packages::Package::toSchema() : erPhysical::Schema when { self.hasClasses() }
{ init {
var classes :=
self.ownedMembers.oclAsType(uml20::classes::Class);
}
object {
name := self.name;
visibility := self.visibility;
entities += classes.toEntityInitial();
}
圖19. toSchema 函數程式碼
2.7.4 toEntityInitial 函數
toEntityInitial函數輸入來源為類別圖,輸出為實體資料表,在init部分使用 resolve語法並輸入新增模型之Meta-Model參數(erPhysical::Entity)(圖20),並 放 入 目 標 模 型 的 結 果 中 (result ), 表 示 目 標 模 型 將 新 增 實 體 資 料 表
(erPhysical::Entity),object則將新增的實體資料表之名稱進行定義,達成轉換 之目的。
mapping
uml20::classes::Class::toEntityInitial() :erPhysical::Entity { init {
result :=
self.resolve(erPhysical::Entity)->any(true);
}
object erPhysical::Entity { name := self.name;
} }
圖20. toEntityInitial 函數程式碼
2.8 小結
透過本章節文獻探討,了解物件導向分析中UML的類別圖形、MDA的轉換 架構與QVT的技術架構,並藉由QVT基本語法與架構之介紹,進一步應用在模 型轉換上,了解模型轉換是從大範圍至小範圍依序使用函數呼叫的方式,階層式 的進行轉換[13],在主要進入點中定義目標模型的內容外,也鎖定其來源模型中 的元素集合並呼叫其他函數進行轉換,例如轉換一個擁有屬性的類別圖,程式碼 首先定義進入點為類別圖後,在主體內容呼叫函數對類別圖所包含的屬性進行轉 換,而被呼叫的函數中可能又會呼叫其他函數來針對屬性中的元素做轉換,QVT 就是依此規則一層一層的將來源模型轉換至目標模型中。
第三章 QVT 轉換規則
本章以第二章的QVT語言為基礎,說明如何將以自然語言表示的模式轉換規 則以QVT程式表達。由於模式轉換規則有無限種需求與可能,本研究以辛信興 [32]所制定的PIM至PSM轉換規則為範圍,其包含三部分:使用者介面轉換規則、
企業邏輯轉換規則與後台資料庫轉換規則。於3.1節介紹轉換規則,3.2節是規則 的QVT程式碼。
3.1 模式轉換規則:自然語言表示法
下述規則係針對三層式架構系統,使用者端是網頁介面(HTML)、應用程 式伺服器端採用PHP、資料庫端採用MySQL,其使用者介面詳細轉換規則如表 10、企業邏輯詳細轉換規則如表11以及後台資料庫轉換規則如表12。
表10. 使用者介面轉換規則
No 轉換規則
P1. 框架集合(Frameset)透過指標類別(Targets)指引,當 Client Page 使用 到框架集合時,其內容會透過指標的存取顯示在框架集合中。
P2. 在 Client Page 中所有 form 型式的元素將產生出一類別圖,其型別命名為 Form,與 Client Page 擁有 Composition 關聯以及與 Server Page 擁有 Dependency 關聯。
P3. 當 PSM 為 HTML 技術平台,將 PIM 中的介面類別轉換為 Client Page 至 PSM;介面類別當中的屬性型別轉換為與 HTML 相對應的屬性型別至 Client Page 中。
P4. PIM 中從控制類別到介面類別的 Dependency 關聯線將在 PSM 產出一個由 Server Page 到 Client Page 的 Dependency 關聯線,其中 Server Page 由控制 類別產生,Client Page 由介面類別產生。
表11. 企業邏輯轉換規則
No 轉換規則
B1. 將 PIM 中控制類別轉換成 Server page 類別圖至 PSM。
B2. 在 PIM 中控制類別的所有屬性,都將會轉換為相對應的屬性至 PSM。
B3. 在 PIM 中控制類別的所有屬性型別,都將會轉換為相對應的屬性型別至 PSM。
B4. 在 PIM 中控制類別的所有操作,都將會轉換為相對應的操作至 PSM。
B5. 在 PIM 中的 Non-persistent entity class 將會轉換為 JavaBean 類別圖至 PSM 中,而Non-persistent entity class 當中的屬性將轉換至 JavaBean 類別圖中 且型別轉換為與PSM 相對應的平台。
B6. 在 PIM 中控制類別與 Persistent entity class 之間的關聯線會轉換為從 Server page 類別圖連結至 Table 類別圖的 Dependency 關聯線。
表12. 後台資料庫轉換規則
No 轉換規則
D1. 當 PSM 為關聯資料庫技術時,將 PIM 中的 Persistent entity class 轉換成 Table 類別圖至 PSM,Persistent entity class 中的屬性型別轉換為與關聯資 料庫技術相對應的屬性型別至PSM 中。
D2. 當 PSM 為關聯資料庫技術時,將 PIM 中的 Association class 轉換成 Table 類別圖至PSM,Association class 中的屬性型別轉換為與關聯資料庫技術 相對應的屬性型別至PSM 中。
D3. 在 PIM 中兩個 Persistent entity class(類別 A 與類別 B)與其之間多對多的 關聯關係所產生的Association class(類別 C),將會轉換為三張Table 類別 圖,類別A 轉成 Table A;類別 B 轉成 Table B;類別 C 轉成 Table C,其 多對多關聯線將轉換為兩條關聯線:Table A 連結至 Table C 的一對多關聯 線,與Table B 連結至 Table C 的一對多關聯線。
D4. 在 PIM 中 Persistent entity class 將轉換為 Table 類別圖,其關聯線將以相同 基數轉換至PSM 中。
3.2 模式轉換規則:QVT 語言表示法
本節針對使用者介面層之轉換規則、企業邏輯層之轉換規則與資料層之轉換 規則,逐一說明轉換規則,並展示相對應的QVT程式碼。
3.2.1 使用者介面層之轉換規則
規則P1
規則P1將介面類別產生出 Frameset 以及 Target 兩個類別與連結至 Client Page 的關聯線,其轉換規則以圖形化方式呈現如,由於本研究在撰寫 QVT-O 的 語法上其轉換方式為先對應來源圖形後再執行轉換,對於PIM 中未出現的圖形,
無法對應並執行轉換,故僅以圖形化的方式呈現。
來源模型 目標模型
P1 規則
圖21. P1規則之轉換圖 規則P2
規則P2將介面類別中 Form 型式的元素產生出 Form 型態的類別圖與連結至 Client Page 以及 Server Page 的關聯線,其轉換規則以圖形化方式呈現如,由於 本研究在撰寫QVT-O 其轉換方式為先對應來源圖形後再執行轉換,對於 PIM 中 未出現的圖形,無法對應並執行轉換,故僅以圖形化的方式呈現。
來源模型 目標模型
P2 規則
圖22. P2規則之轉換圖
規則P3
規則P3將介面類別轉換為 Client Page,並將其包含之屬性型別轉換至 HTML 相對應的型別,其轉換規則以圖形化方式呈現如 圖 23,所對應之 QVT 程式如 表13。首先以名稱為 toClass 的函數轉換類別圖,函數定義來源模型為類別圖,
目標模型也是類別圖,在 init 程式區塊使用 resolve 語法新增類別圖至目標模型 中,而在object 程式區塊定義目標類別圖名稱為 self.name,也就是與來源類別圖 名稱相同,並將來源類別圖型別stereotypes 傳入 PHPstereotype 函數,該函數判 斷當來源為介面類別時,將之改變為 Client class 並回傳,達到轉換之目的。此 外,由於類別圖型別以集合類型儲存,該函數中包括傳入值傳出值以及判斷,都 以集合方式進行。最後在object 程式區塊呼叫 toAttributes 函數進行屬性的轉換。
toAttributes 函數用以轉換屬性以及其型別,函數定義來源為屬性,目標模型也為 屬性,在init 程式區塊使用 resolve 語法新增屬性至目標類別圖中,object 程式區 塊定義目標屬性名稱與來源相同,屬性的type 則呼叫 uml2PHP 的 query 判斷函 數,傳入來源的屬性型別與名稱,經轉換後傳出 PHP 的型別,例如,當來源屬 性型別為String 時,將之改變為 VARCHAR2 並且回傳,達到更改屬性型別之目 的。
來源模型 目標模型
P3 規則
圖23. P3規則之轉換圖
表13. P3規則與其對應語法
P3:當 PSM 為 HTML 技術平台,將 PIM 中的介面類別轉換為 Client Page 至 PSM;介面類別當中的屬性型別轉換為與 HTML 相對應的屬性型別至
P3:當 PSM 為 HTML 技術平台,將 PIM 中的介面類別轉換為 Client Page 至 PSM;介面類別當中的屬性型別轉換為與 HTML 相對應的屬性型別至