`
baiguomeng
  • 浏览: 959697 次
文章分类
社区版块
存档分类
最新评论

使用WTP跨文件持久化EMF对象

 
阅读更多

记得刚开始使用EMF时,我就觉得它跨文件保存对象的功能非常强大方便。
而使用WTP持久化EMF对象就没有这么方便了。毕竟WTP对保存的格式做了
严格的限制。

为了实验,我随便建立了一个模型,如下所示:

Shiep代表学校,包含若干系,每个系有若干老师。
Document是每个老师的档案,Documents是包含Document的容器。

建立这样一个模型的原因:学校要求把学校资料和老师档案分开保存。
这样Document就不能象平时一样把Document和Teacher设为包含(containment)关系。

一,EMF持久化
如果使用EMF自带的保存方法,建立完模型也就结束了:)

1.保存对象的代码片断:
Shiepshiep=ModelFactory.eINSTANCE.createShiep();

Departelectric
=ModelFactory.eINSTANCE.createDepart();
electric.setName(
"electric");
shiep.getDeparts().add(electric);

Teacherandy
=ModelFactory.eINSTANCE.createTeacher();
andy.setName(
"andy");

electric.getTeachers().add(andy);

ResourceshiepRes
=resourceSet.createResource(URI
.createURI(
"file:///home/winters/emftest/shiep.xml"));
shiepRes.getContents().add(shiep);

Documentsroot
=ModelFactory.eINSTANCE.createDocuments();

Documentd1
=ModelFactory.eINSTANCE.createDocument();
d1.setOwner(andy);
//这个andy对象就是跨文件保存的对象
d1.setContent("Heisaverygoodteacher.");

root.getChildren().add(d1);

ResourcedocumentsRes
=resourceSet.createResource(URI
.createURI(
"file:///home/winters/emftest/documents.xml"));
documentsRes.getContents().add(root);

shiepRes.save(
null);
documentsRes.save(
null);


2.看看EMF的保存结果:
Shiep.xml:

<?xmlversion="1.0"encoding="ASCII"?>
<org.shiep.edu.model:Shiepxmlns:org.shiep.edu.model="http:///org/shiep/edu/model.ecore">
<departsname="electric">
<teachersname="andy"/>
</departs>
</org.shiep.edu.model:Shiep>


Document.xml:

<?xmlversion="1.0"encoding="ASCII"?>
<org.shiep.edu.model:Documentsxmlns:org.shiep.edu.model="http:///org/shiep/edu/model.ecore">
<childrencontent="Heisaverygoodteacher.">
<ownerhref="shiep.xml#//@departs.0/@teachers.0"/>
</children>
</org.shiep.edu.model:Documents>


在Document.xml中EMF使用了<owner href="shiep.xml#//@departs.0/@teachers.0"/>这
一行来表示其它文件中的对象。

3.对象保存好了,从文件中读取对象的过程也非常方便。
读取对象的代码片断:

ResourcedocRes=resourceSet.getResource(URI.createURI("file:///home/winters/emftest/documents.xml"),true);
ResourceshiepRes
=resourceSet.getResource(URI.createURI("file:///home/winters/emftest/shiep.xml"),true);

Documentsroot
=(Documents)docRes.getContents().get(0);
TeacherandyFromDoc
=((Document)root.getChildren().get(0)).getOwner();

Shiepshiep
=(Shiep)shiepRes.getContents().get(0);
TeacherandyFromShiep
=(Teacher)((Depart)shiep.getDeparts().get(0)).getTeachers().get(0);

assertEquals(andyFromDoc,andyFromShiep);
//true


就这么简单。

二,WTP持久化
不幸的是我要使用WTP持久化机制来保存对象,这样EMF这么强大的功能我不得不自己来实现了。

1.要使用WTP持久化EMF对象前期准备必须做一些工作。
因为这些地方没有什么特别的,所以我也就不每个都细细来讲了,有兴趣的可以看代码。
1)Translator
因为两个保存得文件是不同的XML格式(使用不同的DTD文件),所以我必须写两个Translator
DocumentsTranslator
ShiepTranslator
2)EntityResolver
同样是两个
DocumentsEntityResolver
ShiepEntityResolver
3)ResourceImpl和ResourceFactoryImpl
全部是double
DocumentsResourceImpl
DocumentsResourceFactoryImpl
ShiepResourceImpl
ShiepResourceFactoryImpl
4)DTD文件
shiep.dtd:
<!ELEMENTshiep(department*)>

<!ELEMENTdepartment(teacher*)>
<!ATTLISTdepartmentnameCDATA#IMPLIED>

<!ELEMENTteacherEMPTY>
<!ATTLISTteachernameCDATA#IMPLIED>

documents.dtd:
<!ELEMENTdocuments(document*)>

<!ELEMENTdocument(owner,content)>
<!ELEMENTowner(#PCDATA)>
<!ELEMENTcontent(#PCDATA)>


2.更改模型
在document.xml文件中,我是使用Teacher的name来标识Teacher的。这样我
必须在Document模型中加上一个OwnerName属性:
/***//**
*@modeltransient="true"volatile="true"
*/

StringgetOwnerName();

transient和volatile表示这个属性是可以在运行期间根据其它信息能够计算出来的。
而ownerName可以根据owner得到。

3.看看WTP保存的结果吧:
shiep.xml:

<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEshiepPUBLIC"publicid""dtds/shiep.dtd">
<shiep>
<departmentname="electric">
<teachername="andy"/>
<teachername="Jacky"/>
<teachername="richard"/>
</department>
</shiep>


document.xml:

<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEdocumentsPUBLIC"publicid""dtds/documents.dtd">
<documents>
<document>
<owner>andy</owner>
<content>Heisaverygoodteacher.</content>
</document>
<document>
<owner>Jacky</owner>
<content>Helikeplayingbasketball.</content>
</document>
<document>
<owner>richard</owner>
<content>Helikecoffee.</content>
</document>
</documents>


4.从文件中读取对象
这个时候没有了EMF的跨文件保存功能,只能自己来一个个匹配了。代码如下:

Shiepshiep=(Shiep)shiepRes.getContents().get(0);
Departdepart
=(Depart)shiep.getDeparts().get(0);
EListteachers
=depart.getTeachers();

ResourcedocRes
=docResourceSet.getResource(URI
.createURI(
"file:///home/winters/emftest2/documents.doc.xml"),
true);
Documentsroot
=(Documents)docRes.getContents().get(0);
EListdocuments
=root.getChildren();

for(Iteratorit=teachers.iterator();it.hasNext();)...{
Teacherteacher
=(Teacher)it.next();
for(IteratordocIt=documents.iterator();docIt.hasNext();)...{
Documentdoc
=(Document)docIt.next();
if(doc.getOwnerName().equals(teacher.getName()))...{
doc.setOwner(teacher);
break;
}

}

}


for(Iteratoriter=documents.iterator();iter.hasNext();)...{
Documentelement
=(Document)iter.next();
System.out.println(element.getOwner()
+":"
+element.getContent());
}


代码输出:
andy : He is a very good teacher.
Jacky : He like playing basketball.
richard : He like coffee.

5.小结:
使用这个我觉得很简单也很原始的方法很直观,但是也有不足之处,那就是我首先做出了这样一个假设:
每个老师的名字都不相同。如果实际情况更加复杂,那就要根据ID之类的来判断了。


附件:
这个例子的代码
http://pickup.mofile.com/3343335105319994
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics