Обновлен: 29 июня 2004 года
Данный справочник представляет собой продолжение справочника Генерация модели EMF, в котором была генерирована простая модель библиотеки. Было показано, как легко можно генерировать модель EMF из модели Rose или набора файлов интерфейсов Java. Теперь мы рассмотрим генерацию модели EMF, расширяющей существующую модель.
Прежде всего вспомним, как выглядела модель библиотеки (модель library):
Расширим теперь эту модель, создав новый пакет schoollibrary (школьная библиотека). Этот пакет содержит три класса, два из которых расширяют классы модели library:
В этом справочнике описывается последовательность создания (генерации) модели EMF данного пакета schoollibrary на основе уже созданной модели library. Как и в предыдущем справочнике будет показано, как создать новую модель из модели Rose и из набора интерфейсов Java.
Моментальные копии экрана соответствуют версии Eclipse SDK версии 3.0 и версии 2.0 среды EMF.
Модель library и соответствующий редактор генерировались в предыдущем справочнике Генерация модели EMF.
Если этих пакетов нет в списке, следует выполнить задания предыдущего справочника или перейти к Приложению, в котором описывается, как создать обе модели одновременно.
Сохраните файл schoollibrary.mdl модели Rose в каком-нибудь каталоге на вашей рабочей станции. Он содержит оба пакета: и library, и schoollibrary.
Пакет, совместно используемый разными моделями, необходимо поместить в его собственный
файл .cat и задать на него ссылку в файле .mdl. Однако в данном справочнике мы просто
копируем и расширяем пакет library в единственном файле модели. Поведение генератора не
зависит от того, содержатся ли пакеты внутри одного файла .mdl, или на них заданы ссылки
во внешних файлах .cat.
Создайте в рабочей области новый проект EMF:
Вот интерфейсы Java с аннотациями для пакета schoollibrary. Модель генератора будет генерироваться не из модели Rose, а из этого файла интерфейсов.
SchoolLibrary.java
package org.eclipse.example.schoollibrary; import org.eclipse.example.library.Library; /** * @model */ public interface SchoolLibrary extends Library { /** * @model */ String getLocation(); }
Asset.java
package org.eclipse.example.schoollibrary; /** * @model */ public interface Asset { /** * @model */ float getValue(); }
SchoolBook.java
package org.eclipse.example.schoollibrary; import org.eclipse.example.library.Book; /** * @model */ public interface SchoolBook extends Book, Asset { }
Создайте в рабочей области новый проект Java:
Можно было бы создать интерфейсы и задать их код так же, как и в предыдущем справочнике, но вместо этого рассмотрим, как импортировать их из архивного файла schoollibrary.zip. Сохраните этот файл в каком-нибудь каталоге на вашей рабочей станции.
Создайте модели EMF:
Модель генератора отображает корневой объект, представляющий всю модель целиком. Дочерние объекты корневого объекта представляют пакеты, входящие в данную модель.
При создании кода должна автоматически выполняться его компиляция, а при изменении - повторная компиляция. Если в параметрах рабочей области среды отключена автоматическая компоновка, то при любых изменениях кода не забудьте выполнять его перекомпоновку.
Для того чтобы протестировать созданные модули, необходимо запустить второй экземпляр Eclipse, называемый рабочей средой выполнения. Модули будут запускаться в этой рабочей среде.
Теперь для создания нового экземпляра модели можно использовать мастер создания модели школьной библиотеки.
Корневой объект в этом редакторе соответствует ресурсу My.schoollibrary. Обратите внимание, что находящийся под ним объект - действительно школьная библиотека.
Выйдите из среды выполнения и вернитесь в среду разработки.
В этой части справочника будет показано, как изменить код, который уже генерирован. Мы изменим только метку в созданном редакторе, но в пояснительных целях сделаем это несколькими различными способами.
Во-первых, внесем изменение в модель генератора, которое повлияет на генерируемый код.
Проверьте метки времени на генерированных файлах, чтобы убедиться, что в действительности повторно генерировался только файл SchoolLibraryItemProvider.java.
В приведенной ниже таблице перечислены файлы, которые создаются при выборе опции "Генерировать код модели", "Генерировать код модуля edit" и "Генерировать код модуля editor" в контекстном меню различных объектов. Выбор пункта "Генерировать все" эквивалентен выбору всех трех этих пунктов меню.
Генерировать код модели | Генерировать код модуля edit | Генерировать код модуля editor | |
Модель <M> |
plugin.xml <M>Plugin.java * ...плюс файлы для каждого пакета |
plugin.xml plugin.properties <M>EditPlugin.java ...плюс файлы для каждого пакета |
plugin.xml plugin.properties <M>EditorPlugin.java ...плюс файлы для каждого пакета |
Пакет <P> |
<P>Package.java <P>PackageImpl.java <P>Factory.java <P>FactoryImpl.java <P>Switch.java <P>AdaptorFactory.java <P>ResourceImpl.java * <P>ResourceFactoryImpl.java * <P>Validator.java * ...плюс файлы для каждого класса и перечислителя |
<P>ItemProviderAdaptorFactory.java ...плюс файлы для каждого класса |
<P>Editor.java <P>ModelWizard.java <P>ActionBarContributor.java |
Класс <C> |
<C>.java <C>Impl.java |
<C>ItemProvider.java | |
Перечислитель <E> | <E>.java |
* Эти файлы не генерируются по умолчанию.
Теперь мы можем проверить наше изменение.
Предположим, что нам не нравится префикс "School Library" в этой метке и мы хотим от него избавиться. Единственный возможный способ состоит в том, чтобы изменить код, а это очень легко сделать.
Как указывалось в документе Среда EMF.Edit - Обзор, среда EMF.Edit использует поставщики элементов, помимо прочего, для того, чтобы определить какую метку отображать для данного типа объекта. В частности, для этого применяется метод getText(), и именно его и следует изменить.
Реализация getText() теперь отличается от первоначально генерированной реализации. Свойство сущности метки в классе SchoolLibrary в модели генератора больше не влияет на генерируемый код. Это следствие того, что мы удалили тег @generated Javadoc, который запрещал переопределять этот метод при генерации кода.
Предположим теперь, что вы еще не решили, должен ли редактор отображать значение атрибута расположения или атрибута имени. Вместо этого вы хотели бы иметь возможность изменить это значение позже посредством модели генератора. Однако точно известно, что не должен отображаться префикс "School Library". В сущности, это означает, что генерированная реализация должна быть доступна для использования в методе, код которого вводится вручную, и который удаляет этот префикс из любого возвращаемого им текста. Имя нового метода должно быть "getText()", поэтому генерированный метод необходимо переименовать.
К счастью, генератор кода EMF поддерживает следующий механизм: когда метод, для которого он собирается генерировать код, вступает в конфликт с методом, не имеющим тега @generated, генератор ищет метод с таким же именем и суффиксом "Gen". Если такой метод существует и снабжен тегами "@generated", реализация будет генерироваться в этот метод.
Вы можете вернуться обратно в модель генератора, изменить свойство сущности метки, повторно генерировать код и проверить, что именно влияет на созданный код.
Если у вас еще нет базовой модели библиотеки и ее редактора, созданных в отдельных проектах, то модели библиотеки и школьной библиотеки можно создать в одном и том же наборе проектов на одном шаге. Это можно сделать на основе модели Rose или набора интерфейсов Java с аннотациями.
Для модели Rose процесс аналогичен описанному выше, за исключением того, что для генерации кода выбираются оба пакета.
При работе с аннотированными интерфейсами Java оба пакета следует импортировать в один проект Java, прежде чем выполнять генерацию кода.
При запуске рабочей среды выполнения для тестирования нового редактора можно заметить одно небольшое отличие в редакторе для модели library по сравнению с редактором, который создавался отдельно из модели schoollibrary.
Обратите внимание, что доступны три типа потомков, тогда как в предыдущем справочнике их было только два. В их число включается "School Book", который происходит из пакета schoollibrary. Ранее генератор кода не знал о нем, когда генерировал поставщик элементов для Library. Но теперь, поскольку оба пакета генерируются вместе, базовый пакет "все знает" о пакете, который его расширяет.