Eclipse Modeling Framework (EMF) 廣泛用於建立健壯的模型層,EMF Query 作為 EMF Technology (EMFT) 子專案,提供宣告式查詢 API,降低處理複雜模型的難度。本文以 Library 模型為例,示範如何建立模型、編寫查詢條件、執行查詢與測試。
Library 模型包含三個類別:Library、Writer、Book,以及一個 BookCategory 列舉。關聯關係:Library 包含多個 Writer 與 Book,Book 可有多位 Writer。
test.emf.query,啟用獨立源碼/輸出目錄model 目錄放入 library.ecoreNew > EMF Model 產生 Library.genmodelemf.modelplugin.xml 的 Dependencies 頁加入 org.eclipse.emf.query 相依查詢框架遍歷模型元素,開發者撰寫繼承自 Condition 的類別判斷元素是否符合。常用條件類別:
| 類別 | 用途 |
|---|---|
EObjectCondition | 所有 EMF 模型查詢條件的基類,接收 PruneHandler 決定是否遞迴子物件 |
EObjectAttributeValueCondition | 檢查屬性值是否滿足條件,接收屬性與值條件(如 NumberCondition) |
EObjectReferencerCondition | 檢查目前物件是否引用特定物件 |
public Collection queryLargeBook(EObject root) {
SELECT select = new SELECT(
new FROM(root),
new WHERE(
new EObjectAttributeValueCondition(
LibraryPackage.eINSTANCE.getBook_Pages(),
new NumberCondition.IntegerValue(new Integer(500), Integer.MAX_VALUE)
)
)
);
return select.execute();
}
public Collection queryBookByWriter(EObject root, Writer writer) {
SELECT select = new SELECT(
new FROM(root),
new WHERE(new EObjectReferencerCondition(writer))
);
return select.execute();
}
private class ThreeWriterCondition extends EObjectCondition {
public ThreeWriterCondition() { super(PruneHandler.NEVER); }
@Override
public boolean isSatisfied(EObject eObject) {
if (eObject instanceof Book) {
Book book = (Book) eObject;
return book.getWriter().size() == 3;
}
return false;
}
}
// 使用方式
public Collection queryBookWithThreeWriters(EObject root) {
return new SELECT(new FROM(root), new WHERE(new ThreeWriterCondition())).execute();
}
使用 JUnit 4.0(@Test、@Before 註解)驗證查詢結果。測試資料建立於 setUp():建立 Library、Writer、Book 實例並建立關聯。測試方法分別驗證三個查詢函式的回傳集合正確性。
EMF Query 以 SQL 風格的 SELECT-FROM-WHERE API 與豐富的 Condition 階層,讓模型查詢變得直觀且可擴充。結合自訂 Condition,可處理任意複雜的查詢需求。EMFT 還包含 OCL、Teneo、Transaction、Validation、Net4J 等元件,值得模型驅動開發者深入探索。