`

EMF开发指南之客户端编程

阅读更多
★emf 运行时编程
★通过package和factory我们可以非常方便的取得class的metamodel信息,并且创建class instance。
★EClass,EPackage,EFactory提供了一些通用的方法,由此派生而来的class,package,factory则提供了更多便利的方法以供我们使用。
★访问指定的class除了通过package的getXxxx()方法之外,还可以取得那些没有generated的class,其用法是XxxxPackage.getEClassifier("Yyyyy")。
★通过package,我们可以遍历访问所有的class(以及attribute,reference,operation),datatype,enumeration
★访问package中所有的类使用EPackage.getEClassifiers()方法,遍历EClass所有属性用EClass.getEAttributes()方法,遍历reference用EClass.getEReferences()方法
★通过package创建制定类实例的几种做法:第一种就是使用XxxxPackage.createYyyy();第二种则是先通过XxxxPackage.eINSTANCE.getYyyyy()这种方式得到相关的实例类,以及XxxxFactory.eINSTANCE得到factory实例,最后使用xxxxFactory.create(yyyyClass)创建实例。
★通过一个给定的class name和相关的package uri创建类实例,一般为了得到类实例,我们需要得到class以及factory,而这些都可以通过package取得(通过getEClassifier()和getEFactoryInstance()方法)
★EPackage是对ecore xml文件的一个序列化对象,因此可以直接使用resouce,从一个ecore文件得到package对象,实际上这是一种比较底层的做法,通常我们不这样做,而是通过使用Package的Registry来映射到给定uri的package对象,Registry从java.util.Map继承而来,通过uri跟一个Package或者Package.Discriptor关联,这里的Discriptor主要在plugin模式下使用,除非真的需要Package,否则在初始化的时候将Discriptor注册到Registry中。在需要使用Package的时候,则通过Discriptor来取得(通过调用其getEPackage()方法),通过EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(packageNsURI)方法,我得到了package,接着得到class name和factory以及最终所需要的class instance就易如反掌了。
★emf presistence framework
★emf的持久化机制主要围绕4个接口:Resource,ResourceSet,Resource.Factory, URIConvertor。通过这4个接口便可以实现emf model的加载和保存
★URI 统一资源标识是一个标识和定义各种类型(文件、网络、数据库、文件对象以及数据流)资源开放标准。一个URI由三部分组成:scheme,scheme-specific以及fragment(可选)。org.eclipse.emf.common.util.URI是对URI的一种封装,scheme标识访问resource协议,文件为file,jar为jar,eclipse为platform
★file:/c:/dir1/dir2/myfile.xml和file:///c:/dir1/dir2/myfile.xml表示的资源是同一个,但是却是不同的URI对象
★scheme-specific由authority,device以及其他的segment组成,authority由//打头,device和segment都是以/打头,uri中从#开始往后都是fragment
★emf使用带有fragment的URI就可以引用到指定的EObject
★URIConvertor 用来将一个uri跟一个实际的uri建立映射关系,比如将一个namespace uri(http:///com/example/epo2.ecore)映射为一个物理uri(platform:/resource/project/somemodel.ecore),它还有一个功能就是normalize,也就是convert的意思,没明白这个机制
★URIConvertor提供createInputStream() and createOutputStream()两个方法,用来在制定的uri上打开两个input和output stream。
★Resouce表示一个EObject集合的持久容器,可以通过URI来进行定位,Resource.getContents()的add方法向一个Resource添加一个EObject,也可以通过给容器类型的关联添加一个引用来给Resource添加一个EObject,Resource比较重要的是save()和load()方法,这两个方法定义了持久化的格式,还有getEObject()和getURIFragment()方法则用来使用URI查找对象
★save和load方法的实现机制:首先使用URIConvertor将指定的uri进行转换,然后打开相应的stream,接着调用doSave和doLoad方法,这些方法交给子类去实现,在save和load两个方法调用中会传一个map参数,这个参数用来控制save和load的行为
★Resource.Factory 用来创建resoruce对象的,所有的factory都使用一个map的registry来加以管理,跟package的registry一样的做法,不同之处它是根据uri scheme以及extension来进行分类注册的。在plugin中默认情况下所有的emf model都使用XMIResourceFactoryImpl,如果要自定义factory,可以通过添加扩展点org.eclipse.emf.ecore.extension_parser,并指定自己的factory实现,一般情况下resource factory只是用来给resourceset来使用
★ResourceSet 用来管理已经load和create的resource集合,主要使用createResource(),getResource(),getEObject()这几个方法。createResource()用于在set中创建一个空的resource对象,getResource()也会先创建一个Resource,然后用指定的resource URI去加载指定的resource,getEObject()则在已有的resource(或者根据uri调用getResource()方法先加载resource)中根据需要加载EObject,
★除了可以直接通过new以及resource.factory的createResource()方法来创建resource对象之外,也可以通过调用ResourceSet的getResource() and createResource()方法来创建(其内部会调用resource.factory的相应方法),这样做的一个重要原因是它能够跟踪某个uri是否已经被打开,这样可以避免内存里面出现两份一样的resource,resource set还可以按需加载当前resource对另外一个resource的引用
★使用ResourceSet的时候需要resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(Resource.Factory.Registry.DEFAULT_EXTENSION,new  XMIResourceFactoryImpl());这样设置一把,否则会因为找不到rsourceFactory而无法使用resource

★emf resource implementation
★在生成一对一的属性的时候,会在当前节点上以attribute的形式添加
★在生成一对多的属性的时候,会在当前节点中以子节点的方式添加属性
★在生成包含关系的引用的时候,会在当前节点中以子节点的方式添加引用节点
★在生成非包含关系的引用的时候,会在当前节点中以attribute的形式引用子节点的fragment,但是如果设置在被包含引用的iD属性的话,则采用id的方式加以引用。
★在创建交叉引用的时候需要把resource的save放在所有resource生成之后。交叉引用可以使用相对路径也可以使用绝对路径,但是相对路径更好一些,因为可移植性更好,要做到使用相对路径引用,则需要在创建resource的时候使用绝对uri路径
★如果引用存在继承关系,那么对于引用的具体子类,会在生成的xml中添加xmi:type属性来表明具体引用的是哪个子类

★xml输出的定制
★OPTION_DECLARE_XML为false标识没有xml头声明
★OPTION_LINE_WIDTH好像没有效果
★OPTION_USE_ENCODED_ATTRIBUTE_STYLE 为true则总是使用uri方式来进行引用
★OPTION_SKIP_ESCAPE为true(默认为true)表示针对转义字符(<,>,&)进行转换
★OPTION_XML_MAP 用来将制定的节点内容进行转换
★OPTION_ENCODING为xml设置字符集
★xml输入定制
★OPTION_DISABLE_NOTIFY 为true取消触发通知
★OPTION_XML_MAP 在save的时候使用了OPTION_XML_MAP,那么在load的时候也要使用

★adapter编程
★给一个model object添加一个adapter有三种方式:第一种通过model object的eAdapters属性将一个adapter跟model关联起来;第二种通过adapter factory的adapt方法将一个adapter与一个model object关联起来;第三种通过扩展已有的adapter factory创建制定类型的adapter来与model object关联。
★Notification用来封装通知信息,这里除了getNotifier()方法返回通知的发送者之外,还包括通知的类型,发生改变的feature(即 feature id),改动前后的值,如果需要屏蔽掉非状态改变的通知,则可以使用isTouch()方法来实现。
★通过adapter除了可以给一个model object添加一个监听器之外,还可以用来给model object增加一些功能。其做法是先定义一个需要实现功能的接口,然后实现该接口并扩展AdapterImpl实现一个Adapter,并创建一个adapter factory来负责创建该adapter,最后通过adapter factory的adapt()方法将model object与前面定义的接口关联起来,这样model object就被扩展成具有该接口的一些功能了。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics