【问题标题】:How to generate EMF models with Java code如何使用 Java 代码生成 EMF 模型
【发布时间】:2016-10-23 11:07:07
【问题描述】:

我想用 Java 代码生成 EMF 模型。例如,我想创建一个新的 Ecore 建模项目,并构建一个在许多教程中看到的简单模型(即像 vogella tutorial)。但我不想使用 GUI 手动完成。我想学习如何使用EMF-Ecore-API 使用 Java 代码创建模型。

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

有关于这个主题的任何资料吗?如果没有,如何通过 java 代码创建 EMF 模型?

【问题讨论】:

    标签: java eclipse eclipse-emf eclipse-emf-ecore


    【解决方案1】:

    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、包含、超类型......)。一旦你了解了架构,那就很容易了。查看页面底部的 UML 图。

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

    【讨论】:

    • 感谢您的帮助,但我还有一个问题:您将如何在两个类之间创建关系?像普通的 Reference 还是 SuperType 关系?
    • 更新了我的答案
    猜你喜欢
    • 1970-01-01
    • 2011-05-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-02
    • 1970-01-01
    • 1970-01-01
    • 2012-08-30
    • 2018-02-02
    相关资源
    最近更新 更多