看到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應該都不是問題.