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

本文介绍了如何使用EMF进行跨文件持久化对象,并对比了使用WTP进行持久化的复杂过程,包括创建Translator、EntityResolver、ResourceImpl和ResourceFactoryImpl等,以及手动匹配对象的需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

   Shiep代表学校,包含若干系,每个系有若干老师。
   Document是每个老师的档案,Documents是包含Document的容器。
  
   建立这样一个模型的原因:学校要求把学校资料和老师档案分开保存。
这样Document就不能象平时一样把Document和Teacher设为包含(containment)关系。

一,EMF持久化
   如果使用EMF自带的保存方法,建立完模型也就结束了:)
  
   1.保存对象的代码片断:
       
        Shiep shiep  =  ModelFactory.eINSTANCE.createShiep();

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

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

        electric.getTeachers().add(andy);

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

        Documents root 
=  ModelFactory.eINSTANCE.createDocuments();

        Document d1 
=  ModelFactory.eINSTANCE.createDocument();
        d1.setOwner(andy);    
// 这个andy对象就是跨文件保存的对象
        d1.setContent( " He is a very good teacher. " );

        root.getChildren().add(d1);

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

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

       
   2.看看EMF的保存结果:
   Shiep.xml:
  
<? xml version="1.0" encoding="ASCII" ?>
< org .shiep.edu.model:Shiep xmlns:org.shiep.edu.model ="http:///org/shiep/edu/model.ecore" >
  
< departs  name ="electric" >
    
< teachers  name ="andy" />
  
</ departs >
</ org.shiep.edu.model:Shiep >


   Document.xml:
  
<? xml version="1.0" encoding="ASCII" ?>
< org .shiep.edu.model:Documents xmlns:org.shiep.edu.model ="http:///org/shiep/edu/model.ecore" >
  
< children  content ="He is a very good teacher." >
    
< owner  href ="shiep.xml#//@departs.0/@teachers.0" />
  
</ children >
</ org.shiep.edu.model:Documents >


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

   3.对象保存好了,从文件中读取对象的过程也非常方便。
   读取对象的代码片断:
  
       
Resource docRes  =  resourceSet.getResource(URI.createURI( " file:///home/winters/emftest/documents.xml " ),  true );
Resource shiepRes 
=  resourceSet.getResource(URI.createURI( " file:///home/winters/emftest/shiep.xml " ),  true );

Documents root 
=  (Documents) docRes.getContents().get( 0 );
Teacher andyFromDoc 
=  ((Document)root.getChildren().get( 0 )).getOwner();
       
Shiep shiep 
=  (Shiep) shiepRes.getContents().get( 0 );
Teacher andyFromShiep 
=  (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:
<! ELEMENT    shiep             (department*) >

<! ELEMENT    department     (teacher*) >
<! ATTLIST    department     name CDATA #IMPLIED >

<! ELEMENT    teacher         EMPTY >
<! ATTLIST    teacher         name CDATA #IMPLIED >

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

<! ELEMENT    document         (owner, content) >
<! ELEMENT    owner             (#PCDATA) >
<! ELEMENT    content         (#PCDATA) >


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

String getOwnerName();

   transient和volatile表示这个属性是可以在运行期间根据其它信息能够计算出来的。
而ownerName可以根据owner得到。
  
   3.看看WTP保存的结果吧:
shiep.xml:

<? xml version="1.0" encoding="UTF-8" ?>
<! DOCTYPE shiep PUBLIC "public id" "dtds/shiep.dtd" >
< shiep >
< department  name ="electric" >
< teacher  name ="andy" />
< teacher  name ="Jacky" />
< teacher  name ="richard" />
</ department >
</ shiep >


document.xml:

<? xml version="1.0" encoding="UTF-8" ?>
<! DOCTYPE documents PUBLIC "public id" "dtds/documents.dtd" >
< documents >
< document >
< owner > andy </ owner >
< content > He is a very good teacher. </ content >
</ document >
< document >
< owner > Jacky </ owner >
< content > He like playing basketball. </ content >
</ document >
< document >
< owner > richard </ owner >
< content > He like coffee. </ content >
</ document >
</ documents >


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

      
        Shiep shiep  =  (Shiep) shiepRes.getContents().get( 0 );
        Depart depart 
=  (Depart) shiep.getDeparts().get( 0 );
        EList teachers 
=  depart.getTeachers();

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

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

            }

        }


        
for  (Iterator iter  =  documents.iterator(); iter.hasNext();)  {
            Document element 
= (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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值