`

[zt]浅析Eclipse建模框架(EMF)及其动态能力

阅读更多

FROM:http://www.devx.com/Java/Article/29093/0/page/1

he Eclipse Modeling Framework (EMF) is a Java open source framework and code-generation facility for building tools and other applications based on a structured model. While the Eclipse Platform provides a powerful integration framework at the UI and file level, EMF enhances this capability to enable fine-grained data sharing among tools and applications.

Similar to other Java binding frameworks, e.g. JAXB or XMLBeans, given a model, EMF can generate Java source code that will allow you to create, query, update, deserialize, and serialize instances of your models. While the majority of Java binding frameworks support just one class of models, for example XML Schema, EMF supports generating code from XML Schema, UML class diagrams (Rational Rose or UML2), and annotated Java interfaces. In addition to the model code, EMF can also generate a complete application that includes a customizable editor.

The EMF-generated code has a built-in change notification mechanism and supports cross-document references. EMF provides a reflective API to access instances of your models and allows you to dynamically create models. EMF supports validation of model constraints. EMF provides powerful code generation tools that support regeneration of models and merging with user written code.

In this article, we'll explain just what the EMF is, take a look at the basic architecture.

EMF started out as an implementation of the Object Management Group's (OMG) Meta Object Facility (MOF) specification, which standardizes a metamodel for object oriented analysis and design. Over time, EMF was used to implement a large set of tools and thus evolved into an efficient Java implementation of a core subset of the MOF API.

The MOF-like core metamodel (model of a model) in EMF is called Ecore. In the current proposal for MOF 2.0, there is a similar subset of the MOF model, called Essential MOF (EMOF), which is separated out. There are small, mostly naming differences between Ecore and EMOF and therefore EMF can transparently read and write serializations of EMOF, allowing standard interchange of data between tools.

Today EMF's use is widespread. For example, EMF is used to implement the open source XML Schema Infoset Model (XSD), Service Data Objects (SDO), UML2, and Web Tools Platform (WTP) projects at Eclipse. In addition EMF is used in commercial products, such as Omondo EclipseUML and IBM Rational and WebSphere products.

Ecore and the Reflective API
One of the key interfaces in EMF is EObject, which is conceptually equivalent to java.lang.Object. All modeled objects, generated or not, implement this interface in order to provide several important features:

  • Similarly to Java's Object.getClass(), using the eClass() method, you can retrieve the metadata of the instance, i.e., its EClass.
  • On any EMF modeled object you can use the reflective API (eGet(), eSet()) to access its data. This is conceptually equivalent to Java's java.lang.reflect.Method.invoke() method, though much more efficient.
  • From any instance object you can get its container (parent) using the eContainer() method.
  • EObject also extends Notifier, which allows you to monitor all changes to the object's data.

 

As mentioned previously, EMF has its own simple metadata called Ecore. Figure 1 shows the complete class hierarchy of the Ecore metadata. In Figure 1, you can see that EPackage contains information about model classes (EClass) and data types (EDataType). EClass represents a modeled class, and specifies the attributes and references representing the data of instances. EAttribute represents simple data, specified by an EDataType. EReference represents an association between classes; its type is an EClass. EFactory contains methods to create model elements.

To find out more about EMF and Ecore please read the online overview or purchase the Eclipse Modeling Framework (EMF). The EMF Web site has several documents describing how to generate Java code from an XML Schema or UML diagram using EMF.

The next section describes an example which uses Ecore to create a simple model for companies, and then uses dynamic EMF to create, serialize and deserialize instances of this model. If you wish to follow along and you are already an Eclipse user, download and install the EMF 2.1 SDK or any newer version available on the EMF download site. Otherwise, you can download the standalone package, which includes EMF jars that do not have any dependencies on Eclipse and can be used in a standalone application.

Using Dynamic EMF Capabilities
In general, if you have models at development time, it is typically best to generate Java code because in this case your application will use less memory and provide faster access to data (using either the generated or the reflective API). While generating Java code serves a need for most applications, this might not always be the case. You might need to process data without requiring the availability of generated implementation classes. For example, you might not know at development time the model of the data you will be processing, making generated Java code a poor option

Dynamic, i.e., non-generated, classes can be created at runtime in several ways. Let's start by creating a company model programmatically using the Ecore API. The company model describes a company that has a name and departments. Each department is identified by a number and has employees. Each employee has a name. The code below shows an Ecore metamodel that corresponds to this model.

java 代码
  1. EcoreFactory ecoreFactory = EcoreFactory.eINSTANCE;   
  2. EcorePackage ecorePackage = EcorePackage.eINSTANCE;   
  3.   
  4. // create an Company class   
  5. EClass companyClass = ecoreFactory.createEClass();   
  6. companyClass.setName("Company");   
  7.   
  8. // create company name   
  9. EAttribute companyName = ecoreFactory.createEAttribute();   
  10. companyName.setName("name");   
  11. companyName.setEType(ecorePackage.getEString());   
  12. companyClass.getEStructuralFeatures().add(companyName);   
  13.   
  14. //create an Employee class   
  15. EClass employeeClass = ecoreFactory.createEClass();   
  16. employeeClass.setName("Employee");   
  17.   
  18. //add a name attribute to an Employee class   
  19. EAttribute employeeName = ecoreFactory.createEAttribute();   
  20. employeeName.setName("name");   
  21. employeeName.setEType(ecorePackage.getEString());   
  22. employeeClass.getEStructuralFeatures().add(employeeName);   
  23.   
  24. //create a Department class   
  25. EClass departmentClass = ecoreFactory.createEClass();   
  26. departmentClass.setName("Department");   
  27.   
  28. //add department identification number   
  29. EAttribute departmentNumber = ecoreFactory.createEAttribute();   
  30. departmentNumber.setName("number");   
  31. departmentNumber.setEType(ecorePackage.getEInt());   
  32. departmentClass.getEStructuralFeatures().add(departmentNumber);   
  33.   
  34. //department class can contain reference to one or many employees   
  35. EReference departmentEmployees = ecoreFactory.createEReference();   
  36. departmentEmployees.setName("employees");   
  37. departmentEmployees.setEType(employeeClass);   
  38.   
  39. // specify that it could be one or more employees   
  40. departmentEmployees.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);   
  41. departmentEmployees.setContainment(true);   
  42. departmentClass.getEStructuralFeatures().add(departmentEmployees);   
  43.   
  44. // company can contain reference to one or more departments   
  45. EReference companyDepartments = ecoreFactory.createEReference();   
  46. companyDepartments.setName("department");   
  47. companyDepartments.setEType(departmentClass);   
  48. companyDepartments.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);   
  49. companyDepartments.setContainment(true);   
  50. companyClass.getEStructuralFeatures().add(companyDepartments);   
  51.   
  52. //create a package that represents company   
  53. EPackage companyPackage = ecoreFactory.createEPackage();   
  54. companyPackage.setName("company");   
  55. companyPackage.setNsPrefix("company");   
  56. companyPackage.setNsURI("http:///com.example.company.ecore");   
  57. companyPackage.getEClassifiers().add(employeeClass);   
  58. companyPackage.getEClassifiers().add(departmentClass);   
  59. companyPackage.getEClassifiers().add(companyClass);   

 

Using the reflective API you can create and initialize an instance of your model:

java 代码
  1. // get company factory   
  2. EFactory companyFactory = companyPackage.getEFactoryInstance();   
  3.   
  4. // using the factory create instance of company class and    
  5. // set company name   
  6. EObject company = companyFactory.create(companyClass);   
  7. company.eSet(companyName, "MyCompany");   
  8.   
  9. // create an instance of employee class   
  10. EObject employee = companyFactory.create(employeeClass);   
  11. //using reflective API initialize name of employee   
  12. employee.eSet(employeeName, "John");   
  13.   
  14. // create an instance of department class   
  15. EObject department = companyFactory.create(departmentClass);   
  16. department.eSet(departmentNumber, new Integer(123));   
  17. //add "John" to department   
  18. ((List)department.eGet(departmentEmployees)).add(employee);   
  19. // add the department to the company   
  20. ((List)company.eGet(companyDepartments)).add(department);  

 

Serializing and Deserializing Data
To serialize your model instances, you need to put a root object of your instance model into a resource. The EMF org.eclipse.emf.ecore.resource.Resource interface represents a physical storage location (such as file or URL) and provides methods to serialize and load data. Each resource is stored in a ResourceSet, which represents a collection of resources that have been created and loaded together, allowing for references among them. In particular, a ResourceSet keeps track of which resources have been loaded and makes sure that no resource in a ResourceSet is loaded twice.

Because EMF is capable of dealing with multiple model sources, e.g., XML Schema, it is also important to specify which resource implementation should be used for (de)serializing your data. Normally, when you invoke the ResourceSet.createResource(URI) method, it queries the Resource.Factory.Registry to look up a factory that is registered for that URI and uses it to create an appropriate resource implementation. Therefore, before you (de)serialize your data ensure that you register the appropriate resource factory implementation. EMF provides several Resource.Factory implementations:

  • For XML data use org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl.
  • For XMI data use org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl.
  • For Ecore models use org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl.

With these EMF resources in your toolbox, you can use this code to serialize your data:

java 代码
  1. // create resource set and resource    
  2. ResourceSet resourceSet = new ResourceSetImpl();   
  3.   
  4. // Register XML resource factory   
  5. resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xmi",    
  6. new XMIResourceFactoryImpl());   
  7.   
  8. Resource resource = resourceSet.createResource(URI.createFileURI("c:/temp/company.xmi"));   
  9. // add the root object to the resource   
  10. resource.getContents().add(company);   
  11. // serialize resource – you can specify also serialization   
  12. // options which defined on org.eclipse.emf.ecore.xmi.XMIResource   
  13. resource.save(null);  

 

The serialized form of the company.xmi is:

xml 代码
  1. <?xml version="1.0" encoding="ASCII"?>  
  2. <company:Company xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"  
  3. xmlns:company="http:///com.example.company.ecore" name="MyCompany">  
  4.   <department number="123">  
  5.     <employees name="John"/>  
  6.   </department>  
  7. </company:Company>  

 

During deserialization, the namespace URIs of XML data are used to locate the required Ecore packages (which describe the model for your instance documents). Therefore, before you attempt to load any model, ensure that you register the namespace URI for each Ecore package your documents will be using:

java 代码
  1. // register package in local resource registry   
  2. resourceSet.getPackageRegistry().put(companyPackage.getNsURI(), companyPackage);   
  3. // load resource    
  4. resource.load(null);   

 

It is also important to notice the difference between local and global package (EPackage.Registry.INSTANCE) and resource factory (Resource.Factory.Registry.INSTANCE) registries. The global registry is static and therefore any application during lifetime of JVM can access the global registry and possibly overwrite it. To ensure that your registrations do not overwrite global registrations and vice versa, it is typically better to use local resource set registry.

Generating Dynamic Ecore from XML Schema
As mentioned previously, if your model is an XML Schema but you choose not to generate Java classes, you can dynamically create an Ecore model using the XSDEcoreBuilder. This example uses ipo.xsd:

java 代码
  1. XSDEcoreBuilder xsdEcoreBuilder = new XSDEcoreBuilder();   
  2. ResourceSet resourceSet = new ResourceSetImpl();   
  3. Collection eCorePackages =    
  4. xsdEcoreBuilder.generate(URI.createFileURI("c:/temp/ipo.xsd"));   
  5.   

The generate method returns Ecore packages that are created for each URI in this schema. If the schema imports other namespaces, more than one Ecore package is returned. Each package is registered locally in the resource set used to convert schema. Therefore, if you use the same resource set to load your instance XML document, you don't need to register the packages yourself.

Because XML Schema includes more concepts than Ecore, for example wildcards, EMF uses Ecore EAnnotations to record the mapping to XML Schema. During (de) serialization of the data EMF needs to process these annotations. To ensure these annotations are respected during (de) serialization, you must use the XMLResource.ExtendedMetaData option:

java 代码
  1. HashMap options = new HashMap();   
  2. options.put(XMLResource.OPTION_EXTENDED_META_DATA, Boolean.TRUE);   
  3. // refer http://www.w3.org/TR/2004/PER-xmlschema-0-20040318/#ipo.xml   
  4. Resource resource = resourceSet.createResource(URI.createFileURI("c:/temp/ipo.xml"));   
  5. resource.load(options);  

EMF 2.1 also adds a new capability that allows you to convert schemas to Ecore on the fly while loading an XML document that contains an xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute. It also allows you to load an XML document that has no schema associated with it. To use this functionality you need to register org.eclipse.emf.ecore.xmi.impl.GenericXMLResourceFactoryImpl:

java 代码
  1. resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xml",    
  2. new GenericXMLResourceFactoryImpl());   

This article gave you a short introduction to EMF, explaining the core EMF concepts, and provided useful examples on how to exploit the dynamic capabilities of EMF.

Note: The opinions expressed in this paper are those of the authors, not of the IBM Corporation. IBM, alphaWorks, developerWorks, and WebSphere are trademarks of International Business Machines Corporation in the United States, other countries, or both. Rational is a registered trademark of International Business Machines Corporation and Rational Software Corporation, in the United States, other countries or both. Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both. Other company, product and service names may be trademarks or service marks of others.

 

分享到:
评论

相关推荐

    Eclipse建模框架

    Eclipse建模框架(EMF)是一个强大的工具,用于通过建模的方法来简化和加速应用程序的开发。在深入探讨EMF的核心概念之前,需要明确什么是建模以及为什么建模技术在软件开发中如此重要。 建模是一种抽象表示现实...

    Eclipse建模框架开发人员指南

    Eclipse建模框架(Eclipse Modeling Framework,简称EMF)是Eclipse基金会提供的一款强大的建模工具,主要用于构建基于模型的应用程序。它基于统一建模语言(UML)和其他建模标准,为开发者提供了一种在Java环境中...

    Eclipse建模步骤界面演示

    Eclipse建模框架(Eclipse Modeling Framework, EMF)是Eclipse项目的核心组件之一,它提供了一整套用于构建和运行模型的工具和API。EMF基于通用建模语言(Unified Modeling Language, UML),但同时也支持自定义...

    EMF for Eclipse 4.4插件

    基于Eclipse的模型框架 它是Eclipse MDA(Model Driven Architecture)的一个重要组成部分 是Eclipse中许多项目的基础 e g GEF EMF可以将模型转换成高效的 正确的 和易于定制的Java代码

    eclipse建模框架

    通过阅读《Eclipse建模框架》这本书,你可以深入了解EMF的原理、使用方法以及最佳实践,从而更好地利用这一强大的建模工具进行软件开发和系统设计。书中可能会涵盖模型的创建、编辑器的定制、数据持久化、模型转换等...

    eclipse的emf插件

    Eclipse的EMF(Eclipse Modeling Framework)插件是一个强大的模型驱动开发工具,它基于Java构建,用于创建、编辑和管理复杂的数据模型。这个插件是Eclipse IDE的一个重要组成部分,特别适合那些需要进行领域特定...

    emf eclipse

    【标题】"EMF Eclipse" 是一个与Eclipse集成的元建模框架,它允许开发者创建、编辑和操作复杂的模型。EMF(Eclipse Modeling Framework)是基于OMG的MOF(Meta-Object Facility)标准,为开发人员提供了一种在...

    eclipse emf&gef

    Eclipse Modeling Framework(EMF)是Eclipse平台的一部分,它提供了一套完整的工具和服务来支持建模工作。EMF的主要目标是为用户提供一种简便的方式来创建和管理复杂的软件模型。 **1.1.1 框架定位** EMF位于...

    eclipse Activiti 流程图创建缺少 emf jar

    requires 'org.eclipse.emf.transaction 1.4.0' but it could not be found 解决办法:将下载解压后的这三个文件拷贝到eclipse的plugin文件夹下即可解决上述问题 org.eclipse.emf.transaction_1.4.0.v201003 31-1738...

    emf-practice:Eclipse建模框架实践代码

    **Eclipse建模框架实践代码**,简称EMF(Eclipse Modeling Framework),是Eclipse平台下的一个重要组成部分,主要用于构建和操作模型驱动的软件系统。EMF提供了强大的模型创建、存储、序列化和交换的能力,是Java...

    eclipse-emf for activiti 插件 jar包

    org.eclipse.emf.transaction_1.4.0.v20100331-1738.jar org.eclipse.emf.validation_1.7.0.201306111341.jar org.eclipse.emf.workspace_1.5.1.v20120328-0001.jar

    eclipse插件开发EMF api 文档

    EMF(Eclipse Modeling Framework)是Eclipse中用于构建模型驱动工程的重要组件,它是基于Java的框架,提供了一套API来支持数据建模、持久化、序列化以及生成代码等任务。 EMF API文档是开发者理解和使用EMF的关键...

    emf-runtime,eclipse modeling framework

    标签中的"EMF"和"eclipse modeling framework"进一步强调了这个主题与Eclipse的建模框架密切相关。EMF是Eclipse建模工具栈的重要组成部分,它不仅用于构建模型驱动的软件,还可以用于生成代码、执行验证和进行数据...

    eclipse插件emf2.8.0

    EMF是Eclipse项目下的一个重要组成部分,它是一个基于模型的软件开发框架,主要用于构建能够处理结构化数据的应用程序和工具。EMF提供了一套完整的工具链,包括模型到源代码的生成、数据持久化、以及基于模型的编辑...

    EMF建模框架

    ### EMF建模框架知识点详解 #### 一、EMF简介 EMF(Eclipse Modeling Framework)是Eclipse平台下的一个重要子项目,主要用于提供一种基于模型的开发方式。EMF的核心理念是支持模型驱动架构(MDA, Model Driven ...

    Eclipse开发使用GEF和EMF(IBM 红皮书)中英文对照版

    《Eclipse开发使用GEF和EMF》是IBM红皮书系列中的一部经典著作,主要探讨了如何在Eclipse环境中利用GEF(图形编辑框架)和EMF( Eclipse模型框架)进行图形化应用程序的开发。这两项技术是Eclipse平台上的核心组件,...

    groovy-emf-builder:将 Eclipse 建模框架 (EMF) 与 Groovy 结合使用

    groovy-all-1.1-rc-2.jarjunit-4.3.1.jarorg.eclipse.emf.common_2.3.0.v200709252135.jarorg.eclipse.emf.ecore.xmi_2.3.1.v200709252135.jarorg.eclipse.emf.ecore_2.3.1.v200709252135.jarorg.eclipse.emf....

Global site tag (gtag.js) - Google Analytics