看到eclipse3.2里面的GMF, 覺得比較有趣,底層還是用到了EMF. 花了兩天時間仔細研究了以下EMF,的確是個好東西.
EMF根據ecore建模(可以和schema的xsd相互轉換)生成強類型的EMF代碼. 這個強類型更強的地方是可以取得meta信息,從而可以用于校驗和界面輔助信息的生成.類似于動態bean,屬性也可以根據名稱動態取得.
以前考慮過用xsd描述界面, 但是數據載體只能是xml, 即使利用apache的schema編譯工具生成強類型的類,后臺代碼也是xml. 不利于持久化. emf在代碼生成引擎比較智能,可以標記出用戶代碼和自動生成代碼.不會有生成覆蓋問題.
這里做個簡單示例:
1. Ecore:
可以新建Ecore, 建立好以后用GMF可視化編輯(Eclipse3.2RC2)

2. 生成Model:
點擊my.ecore文件,菜單:File->New->Other->Eclipse Modeling Framework->EMF Model
3. 打開生成的my.genmodel, 選擇樹頂點的:Generate Model Code
生成的代碼里面會有一個編譯錯誤. 是中文編程的問題, 中文沒有大小寫(先天不足啊),結果性別這個成員變量和性別類名混淆,出錯.在錯誤代碼前面加上包全名即可.
4. 利用生成的代碼構建一個家庭,輸出xml并且校驗之:
import
?java.io.IOException;
import
?java.util.Iterator;

import
?org.eclipse.emf.common.util.Diagnostic;
import
?org.eclipse.emf.common.util.URI;
import
?org.eclipse.emf.ecore.EObject;
import
?org.eclipse.emf.ecore.resource.Resource;
import
?org.eclipse.emf.ecore.util.Diagnostician;
import
?org.eclipse.emf.ecore.xmi.XMLResource;
import
?org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl;
import
?org.steeven.family.FamilyFactory;
import
?org.steeven.family.人物;
import
?org.steeven.family.家庭;
import
?org.steeven.family.性別;


public
?
class
?TestMy?
{


????
public
?
static
?
void
?main(String[]?args)?
throws
?IOException?
{
????????testFamily();
????}
????
private
?
static
?
void
?testFamily()?
throws
?IOException?
{
????????家庭?family?
=
?FamilyFactory.eINSTANCE.create家庭();
????????family.setTitle(
"
steeven家
"
);
????????family.set老公(FamilyFactory.eINSTANCE.create人物());
????????family.get老公().set姓名(
"
steeven
"
);
????????family.set老婆(FamilyFactory.eINSTANCE.create人物());
????????family.get老婆().set姓名(
"
stella
"
);
????????family.get老婆().set性別(性別.女_LITERAL);
????????人物?sophie?
=
?FamilyFactory.eINSTANCE.create人物();
????????sophie.set姓名(
"
sophie
"
);
????????sophie.set性別(性別.女_LITERAL);
????????family.get兔崽子().add(sophie);
????????dump(family);
????????validate(family);
????}
????
private
?
static
?
void
?validate(EObject?family)?
{
????????Diagnostic?diagnostic?
=
?Diagnostician.INSTANCE.validate(family);
????????System.out.println(diagnostic);

????????
for
?(Iterator?it?
=
?diagnostic.getChildren().iterator();?it.hasNext();)?
{
????????????Diagnostic?diag?
=
?(Diagnostic)?it.next();
????????????System.out.println(diag.getMessage());
????????}
????}
????
private
?
static
?Resource?dump(EObject
?objs)?
throws
?IOException?
{
????????
//
?ResourceSet?rs?=?new?ResourceSetImpl();
????????
//
?rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put(
????????
//
?Resource.Factory.Registry.DEFAULT_EXTENSION,
????????
//
?new?XMIResourceFactoryImpl());
????????
//
?Resource?resource?=?rs.createResource(URI
????????
//
?.createFileURI("c:\\temp\\test.xml"));
????????XMLResource?resource?
=
?
new
?XMLResourceImpl(URI
????????????????.createFileURI(
"
c:\\temp\\test.xml
"
));
????????resource.setEncoding(
"
GBK
"
);
????????
for
?(EObject?obj?:?objs)
????????????resource.getContents().add(obj);?
//
?目前版本不加入resource驗證會報singling異常
????????resource.save(System.out,?
null
);
????????
return
?resource;
????}
}
運行結果如下:
<?
xml?version="1.0"?encoding="GBK"
?>
<
family:
家庭?xmlns:family
="http://org.steeven/family"
?title
="steeven家"
?老公
="/"
?老婆
="/"
?兔崽子
="/"
/>
Diagnostic?ERROR?
The?feature?'老公'?of?'org.steeven.family.impl.家庭Impl@f6a746{file:/c:/temp/test.xml#/}'?contains?a?dangling?reference?'org.steeven.family.impl.人物Impl@6eb38a{#//}'
The?feature?'老婆'?of?'org.steeven.family.impl.家庭Impl@f6a746{file:/c:/temp/test.xml#/}'?contains?a?dangling?reference?'org.steeven.family.impl.人物Impl@1cd2e5f{#//}'
The?feature?'兔崽子'?of?'org.steeven.family.impl.家庭Impl@f6a746{file:/c:/temp/test.xml#/}'?contains?a?dangling?reference?'org.steeven.family.impl.人物Impl@19f953d{#//}'
可見輸出的xml中沒有包含人物的具體信息. 修改my.ecore中老公/老婆/兔崽子屬性的containment屬性為true,重新生成代碼后運行結果如下:
<?xml?version="1.0"?encoding="GBK"?>
<family:家庭?xmlns:family="http://org.steeven/family"?title="steeven家">
??<老公?姓名="steeven"/>
??<老婆?性別="女"?姓名="stella"/>
??<兔崽子?性別="女"?姓名="sophie"/>
</family:家庭>
Diagnostic?OK====================
EMF單獨運行成功~
這里ECORE似乎不支持嵌套定義,不像schema那樣一個complexType聲明里面可以定義的很復雜, 也不像Java的內部類. 似乎被作了簡化, 更像關系數據庫表之間的關系.
待求證問題:
1. EMF的校驗信息是否支持國際化.
2. EMF數據的能否更方便的保存到數據.
EMF的靈活和強大已經驗證過, 用于C/S還是B/S應該都不是問題.