首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

使用 EMF 進行建模,第 3 部分:運用 Eclipse JMerge 客製化生成代碼與編輯器

     編輯:Java 相關知識

前言:代碼生成與客製化的矛盾

前文介紹了 JET(Java Emitter Templates)如何透過模板生成代碼,實現模式級重用。然而實務上常面臨兩難:生成的代碼需要插入既有專案、或開發者需客製化生成代碼,且重新生成時不得覆寫手動修改。JMerge 正是為解決此問題而生的純 Java 合併工具,內建於 EMF 中。

JMerge 核心機制

JMerge 允許定義合併規則,將新生成的原始碼(Source)與已客製化的目標碼(Target)智慧合併。關鍵流程:

  1. 建立 JMerger 實例並載入 merge.xml 控制模型
  2. 設定 Source(新生成代碼)與 Target(現有代碼)的編譯單元
  3. 呼叫 merger.merge() 執行合併
  4. 取得 merger.getTargetCompilationUnit() 寫回目標檔案

進階合併策略

1. 基礎方法體合併

<merge:pull
  sourceGet="Method/getBody"
  targetPut="Method/setBody"/>

將來源類別每個方法的主體合併至目標類別對應方法。目標不存在則建立;僅存在於來源者保留。

2. 區分生成與手動修改代碼:@generated 標記

問題:單純合併會覆寫所有手動修改。解決方案:引入 <merge:dictionaryPattern> 識別標記。

<merge:dictionaryPattern
  name="generatedMember"
  select="Member/getComment"
  match="\s*@\s*(gen)erated\s*\n"/>
<merge:pull
  targetMarkup="^gen$"
  sourceGet="Method/getBody"
  targetPut="Method/setBody"/>
  • dictionaryPattern:掃描 JavaDoc 註解中包含 @generated 的成員
  • targetMarkup:合併規則僅套用於目標代碼同樣帶有 @generated 的方法
  • 開發者刪除 @generated 標記即可保護該方法免被重新生成覆寫

3. 強制不可修改區塊:@unmodifiable 標記

<merge:dictionaryPattern
  name="generatedUnmodifiableMembers"
  select="Member/getComment"
  match="\s*@\s*(unmod)ifiable\s*\n"/>
<merge:pull
  sourceMarkup="^unmod$"
  sourceGet="Member/getBody"
  targetPut="Member/setBody"/>

來源代碼標記 @unmodifiable 的方法,合併時將強制覆寫目標,防止開發者誤刪關鍵邏輯。

4. 細粒度合併:用戶代碼保留區

<merge:pull
  targetMarkup="^gen$"
  sourceGet="Method/getBody"
  sourceTransfer="(\s*//\s*begin-user-code.*?//\s*end-user-code\s*)\n"
  targetPut="Method/setBody"/>

利用正則表達式 sourceTransfer 定義保留區塊(// begin-user-code 至 // end-user-code),僅更新區塊外代碼,實現方法級的部分重生成。

5. JavaDoc 註解細粒度保留

<merge:pull
  sourceMarkup="^gen$"
  sourceGet="Member/getComment"
  sourceTransfer="(\s*<!--\s*begin-user-doc.*?end-user-doc\s*-->\s*)\n"
  targetMarkup="^gen$"
  targetPut="Member/setComment"/>

採 HTML 註解語法 <!-- begin-user-doc --> 包裹用戶可編輯區塊,不影響 JavaDoc 輸出。

JMerge 支援的 Java 元素完整對照表

附錄 A:有效目標選項

類型可存取屬性/方法
CompilationUnitgetHeader/setHeader, getName/setName
FieldgetInitializer/setInitializer, getName/setName
ImportgetName/setName
InitializergetName/setName, getBody/setBody
MembergetComment/setComment, getFlags/setFlags (abstract, final, native...)
MethodaddException, addParameter, getBody/setBody, getName/setName, getParameterNames/setParameterNames, getParameterTypes/setParameterTypes, getReturnType/setReturnType
PackagegetName/setName
TypeaddSuperInterface, getName/setName, getSuperclass/setSuperclass, getSuperInterfaces/setSuperInterfaces

附錄 B:merge:pull 屬性說明

屬性必要性說明
sourceGet必要來源存取路徑,如 Method/getBody
targetPut必要目標寫入路徑,如 Method/setBody
sourceMarkup可選來源代碼需符合的 dictionaryPattern,格式 ^name$
targetMarkup可選目標代碼需符合的 dictionaryPattern
sourceTransfer可選正則表達式,指定從來源傳輸至目標的代碼片段

實務參考範例

  • plugins/org.eclipse.emf.codegen_1.1.0/test/merge.xml:基礎合併範例(異常、旗標、Import 等)
  • plugins/org.eclipse.emf.codegen.ecore_1.1.0/templates/emf-merge.xml:EMF 官方合併策略,支援 JavaDoc 部分客製化

結合上述技巧,可進一步擴充方法體級別的客製化支援,強化 JET 代碼生成的實用性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved