如何使用 Java 代码生成 EMF 模型

How to generate EMF models with Java code

我想用 Java 代码生成 EMF 模型。例如,我想创建一个新的 Ecore 建模项目,并构建一个如许多教程中所示的简单模型(即像 vogella tutorial). But I don't want to do that by hand, using the GUI. I want to learn how to create a model with Java code, using the EMF-Ecore-API

我试图找到关于这个主题的教程。但令我失望的是,我找不到太多关于这个话题的信息。我唯一能找到的是一些 code snippets to load and modify existing models by code。但与创建新模型无关。只是浏览 API 对我没有帮助。

是否有关于此主题的资源?如果没有,我如何通过 java 代码创建 EMF 模型?

IBM 有一个关于动态 EMF 的主题。

但如果您熟悉 emf 中的创建工作方式,则它非常简单。每个 EPackage 都有自己的 EFactoryEPackage 实例,它们处理创建(工厂)或存储有关元模型本身(epackage)的信息。

Ecore 有自己的 EPackageEFactory,所以绝对可以像这样即时创建新的元模型:

    /*Use the Ecore factory*/
    EcoreFactory ecoreFactory = EcoreFactory.eINSTANCE;
    /*Create your EPackage*/
    EPackage myPackage = ecoreFactory.createEPackage();
    /*set EPackage properties*/
    myPackage.setName("myTest");
    myPackage.setNsPrefix("myTest");
    myPackage.setNsURI("http://com.myTest");

    /*Create your first EClass*/
    EClass myFirstEClass = ecoreFactory.createEClass();
    myFirstEClass.setName("myClass");
    /*Add to your EPackage's EClassifiers*/
    /*EClasses and EDatatypes implement both EClassifiers*/
    myPackage.getEClassifiers().add(myFirstEClass);

    /*Create your first EAtttribute*/
    EAttribute myFirstEAtt = ecoreFactory.createEAttribute();
    myFirstEAtt.setName("name");
    /*Use the EcorePackage Datatypes -> here EString*/
    myFirstEAtt.setEType(EcorePackage.eINSTANCE.getEString());
    /*use EStructuralFeatures to add your EAtt*/
    /*EReferences and EAttributes are both EStructuralfeatures*/
    myFirstEClass.getEStructuralFeatures().add(myFirstEAtt);

更新:

    /*Create your second EClass*/
    EClass mySecondEClass = ecoreFactory.createEClass();
    mySecondEClass.setName("mySecondClass");
    myPackage.getEClassifiers().add(mySecondEClass);

    /*now, the firstClass should hold instances of secondClass*/
    /*1. create EReference (Ereferences unlike EAttributes define relationships between EClasses)*/
    EReference secondClassesRef = ecoreFactory.createEReference();
    secondClassesRef.setName("secondClasses");
    /*set containment true -> every EObject must have a Container*/
    secondClassesRef.setContainment(true);
    /*set Type to your EClass*/
    secondClassesRef.setEType(mySecondEClass);
    /*set upperbound -> now the reference is an EList*/
    secondClassesRef.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);

    /*finally add ERef to EClass*/
    myFirstEClass.getEStructuralFeatures().add(secondClassesRef);

    /*and for example supertypes*/
    myFirstEClass.getESuperTypes().add(mySecondEClass);

现在您有了自己的 EPackage 和一个新的 EClass,它的 EAttribute 名称类型为 EString

现在也可以将新的 EPackage 保存到 .ecore 文件,如下所示:

    /*
     * Save your EPackage to file ecore file:
     */

    /*Initialize your EPackage*/
    myPackage.eClass();
    Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
    Map<String, Object> m = reg.getExtensionToFactoryMap();
    /*add default .ecore extension for ecore file*/
    m.put(EcorePackage.eNAME, new XMIResourceFactoryImpl());

    // Obtain a new resource set
    ResourceSet resSet = new ResourceSetImpl();
    // create a resource
    Resource resource = null;
    try {
        resource = resSet.createResource(URI.createFileURI("/Your/Path/To/Directory/myTest.ecore"));
    } catch (Exception e) {
        e.printStackTrace();
    }
    /*add your EPackage as root, everything is hierarchical included in this first node*/
    resource.getContents().add(myPackage);

    // now save the content.
    try {
        resource.save(Collections.EMPTY_MAP);
    } catch (IOException e) {
        e.printStackTrace();
    }

反之亦然,如果您想加载现有的 ecore EPackage:

    /*
     * load existing EPackage
     */
    EcorePackage.eINSTANCE.eClass();
    /*Initialize your EPackage*/
    final Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
    final Map<String, Object> m = reg.getExtensionToFactoryMap();
    m.put(EcorePackage.eNAME, new XMIResourceFactoryImpl());

    final ResourceSet resSet = new ResourceSetImpl();
    Resource resource = null;
    try {
        resource = resSet.getResource(URI.createFileURI("/Your/Path/To/Directory/myTest.ecore"), true);
    } catch (Exception e) {
        e.printStackTrace();
    }
    /*load root and cast to EPackage*/
    final EPackage root = (EPackage) resource.getContents().get(0);

更新: Ecore 当然有自己的元模型。在 Docs 中,您可以找到对 ecore 架构的精彩概述。

因此,如果您想使用动态 EMF,则需要了解这一点。正如我向您展示的,动态创建一个 EPackage 非常简单,但是您需要知道如何设置 ecore 模型的基本属性(EClass、EAttributes、EReferences、EType、containment、supertypes ...) .一旦你理解了架构,那就很容易了。查看页面底部的 UML 图。

我还更新了上面的代码,向您展示如何初始化 EClasses 之间的关系