EMF学习笔记(四)——使用EMF编程——持久化(续)

本文详细探讨了EMF的持久化框架,特别是XMLResourceImpl如何处理EMF对象的序列化和反序列化。默认情况下,仅序列化设置了的属性和引用,以节省存储。XMLResourceImpl使用SAX进行加载,而XMIResourceImpl支持XMI标准,增加了如xmi:XMI元素以处理多对象情况。XMIResource提供了使用UUIDs的选项,并在Eclipse中作为默认的持久化格式。

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

持久化(Persistence)

持久化框架的概述

EMF持久化API

XML资源

  EMF针对基于XML资源的基础接口,XMLResource,扩展Resource加入了数个与持久化形式相关的方法。基础实现,XMLResourceImpl,可以用来将任一EMF 序列化为XML。它产生消耗(consume)的XML格式,以及它的性能特征,可以有很多种方式来控制
  首先讨论这个实现提供的默认序列化格式,然后是其支持的多个保存加载选项,以及元数据如何被用来自定义(customize)序列化格式,最后,讨论这个实现的一些其他特征,包括其支持的默认选项,外在的IDDOM转换。

默认序列化格式

  为了说明XMLResourceImpl的默认输出格式,我们先创建一个对象并保存,如下:

USAddress address = EPO2Factory.eINSTANCE.createUSAddress();
URI uri = URI.createPlatformResourceURI("/project/out.xml", true);
Resource resource = new XMLResourceImpl(uri);
resource.getContents().add(address);
resource.save(null);

  创建USAddress类的实例,将其加入到XML资源的内容中,然后保存资源。注意此处是显式地(explicitly)实例化XMLResourceImpl,仅仅是为了说明。在练习时,你应该总是通过ResourceSet接口创建资源。
  out.xml中生成的序列化,如下:

<?xml version="1.0" encoding="ASCII"?>
<epo2:USAddress xmlns:epo2="http://www.example.com/epo2.ecore"/>

  首先,在XML声明中指定的编码是ASCII。这是默认的,但并不是特别好的选择。最常使用的是Unicode编码比如UTF-8
  接着看XML声明,使用命名空间,将单个的USAddress序列化成为一个元素。命名空间的前缀(”epo2“)和相应的URI(”http://www.example.com/epo2.ecore“)来自于模型中EPackagensPrefixnsURI属性。
  属性和元素的内容依赖于对应EMF对象的属性和引用。可以回顾USAddress定义的四种简单属性:street, city, state和zip。也许会疑惑为什么它们没有出现在序列化中,这是因为它们之前没有被设置(set)。默认情况下,XMLResourceImpl 序列化器(serializer)仅仅包括被设置的属性和引用(例如反射式的EObject.eIsSet()方法返回为时的)。这种手段通过只包括在加载时需要用来还原(restore)对象状态(state)最少数量的信息,最小化XML文件

反序列化

  XMLResourceImpl加载器使用SAX(the Simple API for XML)来提供加载支持。当文档被解析时,SAX事件被用来在内存建立 EMF 对象。与之对比的是,DOM(the Document Object Model)会构建一个中介(intermediary)模型,消耗更多的内存以及更长的时间来运行。
  在加载过程中,命名空间URIs从声明中读取然后被用来定位对应的Ecore包。这经常涉及到查询包注册,如果加载的资源在资源集合中就是一个重点内容注册,否则就是全局注册。然而,当没有被注册的匹配的包时,加载器自动地使用命名空间URI来将一个资源加载到资源集合中。通常而言,仅仅试图从URI直接加载,如果提供包含EPackage实例的EMF资源,则局部地注册包。这是因为序列化的Ecore模型就是另一个模型,Ecore 元模型的实例,所以才能像其他EMF数据一样被加载。
  (未完待续)

选项

动态EMF

扩展的元数据

其他特征

EMF资源和资源工厂实现

  EMF提供数个基于XML(XML-based)的资源和资源工厂实现。资源负责持久化它包含的对象,资源工厂被用来创建配置资源的一种类型。根本上,是资源工厂决定了为其注册的URI类型生成的和使用的持久化格式。

基础XML

泛型XML

XMI

  XMIResourceImpl继承XMLResourceImpl以支持XML Metadata Interchange (XMI) 2.0 标准。EMF将模型映射到“普通的”XML序列化的方式深受XMI启发,所以两者之间没有大的区别。

<?xml version="1.0" encoding="ASCII"?>
<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
    xmlns:epo2="http://www.example.com/epo2.ecore">
    <epo2:PurchaseOrder xmi:id="_xNSb8KfZEdm0dNl1iq3EdQ"
        comment="rush order">
        <items xmi:id="_xO0F8KfZEdm0dNl1iq3EdQ" productName="apple"/>
    </epo2:PurchaseOrder>
    <epo2:PurchaseOrder xmi:id="_xO0F8afZEdm0dNl1iq3EdQ"
        comment="special promotion"
        previousOrder="_xNSb8KfZEdm0dNl1iq3EdQ">
        <items xmi:id="_xO0F8qfZEdm0dNl1iq3EdQ" productName="orange"/>
    </epo2:PurchaseOrder>
</xmi:XMI>

  注意到根元素有额外的命名空间声明,介绍了XMI命名空间,同来xmi前缀来标识。XMI序列化中的根元素总是包含一个版本属性,来标识使用的XMI的版本
  也许最引人注目的特点是根(root)中额外的xmi:XMI元素。这个元素是XMIResourceImpl引进的,因为两个对象被直接添加到资源的内容列表中。格式良好(well-formed)*XML文档必须有且仅有一个根元素,所以XMI定义了这个元素来处理需要表示多个顶级对象的情况。我们从没有使用普通的***XMLResourceImpl实现这种事情,原因如下:它只是简单地持久化了资源里的第一个对象,而忽视了剩下的对象。
  注意到这个例子中,使用了自动生成的UUIDs。我们使其生效,通过上一章中其他特征建议的方法。注册了资源工厂,其创建了XMLResourceImpl简单子类实例,其中重写useUUIDs() 使其返回为真:

ResourceSet rs = new ResourceSetImpl();
rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put(
    Resource.Factory.Registry.DEFAULT_EXTENSION,
    new ResourceFactoryImpl()
    {
        public Resource createResource(URI uri)
        {
            return new XMIResourceImpl(uri)
            {
                protected boolean useUUIDs() { return true; }
            };
        }
    });

  在XML中使用UUIDs相当普遍,尽管规范中没有要求。EMF的基础XMLResource实现不使用它们,因为默认的基于索引(index-based)段路径(fragment paths)通常更高效。
  XMI资源有个接口,XMLResource,它定义一个额外的选项关键字(option key)OPYION_USE_XMI_TYPE取的是布尔值,仅用于save()。如果它是有效的,xmi:type属性将被用来标识引用的类型,而不是xsi:type
  当在Eclipse中运行时,XMIResourceFactoryImpl被注册为全局注册中的默认资源工厂。换句话说,XMI是默认的持久化格式,当没有其他针对特定URI模式(scheme)或者文件扩展名(file extension)的持久化格式时,使用XMI

Ecore

  EcoreResourceFactoryImpl是创建普通XMIResourceImpl实例的简单资源工厂实现,然后设置编码UTF-8并使某些默认的XMIResourceImpl生效。特别地,编码属性类型(encoded attributes style)用于引用,行宽度设置为80。

EMOF

Generated

性能考量

主动对象的定制存储

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值