Как генерировать модели EMF с помощью кода Java

Я хочу генерировать модели EMF с кодом Java. Например, я хочу создать новый проект моделирования Ecore и построить простую модель, как показано во многих учебных пособиях (например, как руководство по Vogella). Но я не хочу делать это вручную, используя графический интерфейс. Я хочу узнать, как создать модель с помощью кода Java, используя EMF-Ecore-API.

Я пытался найти учебники по этой теме. Но, к моему разочарованию, я не смог найти много по этой теме. Единственное, что я смог найти, это несколько фрагментов кода для загрузки и изменять существующие модели с помощью кода. Но ничего о создании новых моделей. И просто просмотр API мне не помог.

Есть ли источники по этой теме? А если нет, то как я могу создавать модели EMF с помощью java-кода?


person ConveniencePatterns    schedule 23.10.2016    source источник


Ответы (1)


У IBM есть тема о динамическом EMF.

Но это довольно просто, если вы знакомы с тем, как создание работает в emf. Каждый EPackage имеет свои собственные экземпляры EFactory и EPackage, которые обрабатывают создание (фабрика) или хранят информацию о самой метамодели (epackage).

Ecore имеет свои собственные EPackage и EFactory, так что совершенно возможно создавать новые метамодели на лету следующим образом:

    /*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, конечно же, есть собственная метамодель. В документах вы найдете отличный обзор архитектуры ecore.

Поэтому, если вы хотите использовать динамическую ЭДС, вам нужно это понять. Как я показал вам, очень просто создать EPackage динамически, но вам нужно знать, как установить основные атрибуты модели ecore (EClass, EAttributes, EReferences, EType, включение, супертипы...). Как только вы поняли архитектуру, это довольно легко. Взгляните на UML-диаграмму внизу страницы.

Я также обновил приведенный выше код, чтобы показать вам, как инициализировать отношения между EClass.

person Mad Matts    schedule 23.10.2016
comment
Спасибо за вашу помощь, но у меня есть еще один вопрос: как бы вы создали отношение между двумя классами? Как обычная ссылка или отношение SuperType? - person ConveniencePatterns; 24.10.2016
comment
Обновлен мой ответ - person Mad Matts; 24.10.2016