Моделирование при помощи среды Eclipse Modeling Framework: Часть 1. Создание моделей UML и генерация кода

Eclipse Modeling Framework (EMF) — это среда open source, предназначенная для разработки приложений на основе моделей. Она вырабатывает код Java™ для графического редактирования, манипулирования, чтения и сортировки данных на основе модели, описанной в форме XML Schema, UML или аннотированной Java. EMF служит фундаментом многих инструментов в проектах IBM® WebSphere® Studio и Eclipse. В настоящей статье рассматривается процесс создания модели, генерации кода, использования полученных приложений и настройки редактора.

Адриан Пауэлл, старший разработчик ПО, IBM  

Адриан Пауэлл (Adrian Powell) начинал свою деятельность с разработки инструментария Java в отделении VisualAge IBM в качестве члена группы Java Enterprise Tooling. Он потерял два года, программируя генератор кода вручную. С тех пор Адриан разработал инструменты и подключаемые модули почти для каждой версии Eclipse и VisualAge для Java. Сейчас он работает в Центре инноваций электронного бизнеса IBM в Ванкувере, где создает замену самому себе.



26.06.2009

Что такое EMF?

EMF — это среда open source, предназначенная для разработки приложений с применением архитектуры, управляемой моделями (Model-Driven Architecture - MDA). Тем немногим счастливчикам, у кого есть модель UML, она помогает превратить документацию в код. Для остальных это еще одно средство убедить своего босса в том, что время, потраченное на моделирование решения, действительно может окупиться. В дополнение к генерации кода Java со всеми примочками EMF также может генерировать модули Eclipse и настраиваемые графические редакторы. Когда вы меняете свою модель (а это случается регулярно), EMF позволяет синхронизировать код в соответствии с новой моделью нажатием единственной кнопки.

Код, сгенерированный EMF, это не одноразовое решение. Он поддерживает стандартные операции создания, извлечения, обновления и удаления; ограничение на количество элементов; сложные отношения и структуры наследования; а также набор описаний атрибутов. Сгенерированный код гарантирует целостность уведомлений и ссылочных данных. Все, что нужно — это создать объектную модель, что вы, наверное, и так собирались сделать.

EMF — это относительно новый, но, тем не менее, многообещающий подход, причем имеются явные признаки усиления его поддержки. Он реализует открытый стандарт — Meta-Object Facility (MOF)организации Object Management Group — и сейчас поддерживает расширения версии 2 (V2). Более того, EMF лежит в основе проектов Eclipse EMF:XSD и Hyades и используется в большинстве продуктов IBM WebSphere Studio. Разработка V2 уже началась, и скоро ожидается выход сборок для разработчиков. В планы входит лучшая поддержка XML Schema, более гибкая генерация кода и установление соответствия между моделями.


Пусть инструменты говорят сами за себя

Давайте без маркетинговой болтовни. Перейдем прямо к коду и посмотрим, на что реально способен EMF. Во всех приведенных здесь примерах применяются Eclipse V3.0M7 и EMF V2.0.0 с соответствующим набором инструментов XSD. Существует четыре отдельных потока разработки EMF, по одному для каждой версии Eclipse, так что выберите подходящую версию EMF для своей версии Eclipse (эти модули есть в разделе Ресурсы).

Для демонстрации важных особенностей воспользуемся простым примером Web-форума. Корнем нашей модели будет Forum со списком членов (Member) и списком тем (Topic). Каждому значению Topic соответствует TopicCategory (перечислимый тип), причем Member и Topic связаны косвенно, через класс Post, и непосредственно, так как Member может создавать Topic.

Создание модели EMF при помощи UML и Omondo

UML-плагин от Omondo представляет собой удобный и гибкий модуль для создания UML-документов в среде Eclipse. Он напоминает тощего, недокормленного брата Rational® Rose, но когда не нужны дополнительные возможности, работает идеально. К сожалению, он еще не поддерживает Eclipse V3, поэтому для создания схемы класса UML я использовал Eclipse V2.1.

Начните с создания нового проекта Java под названием UMLForum и com.ibm.example.forum. Создайте новую схему класса EMF forum.ucd в каталоге src/com/ibm/example/forum. Создаются два файла: forum.ecd и forum.ecore. Добавьте новый класс Forum и нажмите кнопку Finished. Добавьте к своему классу Forum атрибут description типа EString (для всех простых типов Java имеются типы Ecore), как показано на рис. 1. Из функций выберите только changeable и установите границы от 0 до 1.

Если позднее вы измените свои намерения по поводу этих функций, откройте представление Properties и выберите класс или атрибут.

Рисунок 1. Новый класс Forum со значениями атрибутов
Новый класс Forum со значениями атрибутов

Повторите эти шаги для следующих интерфейсов:

Таблица 1. Интерфейсы
ИнтерфейсАтрибутТип
MembernicknameEString
TopictitleEString
PostcommentEString

Чтобы определить связи, нажмите кнопку Association и выберите источник (Forum) и цель (Member). Откроется диалог Association Properties. Задайте имя members, выбрав только значения changeable и containment, и установите верхнюю границу равной -1. На второй вкладке Association End удалите флажок Navigable и нажмите Ok. Повторите то же для Forum и Topic с именем атрибута topics, вместо members. Удаленный флажок navigable создает односторонние ассоциации, а мы хотим, чтобы наши атрибуты были двухсторонними.

Заполните список ассоциаций следующим образом:

Таблица 2. Ассоциации
ИсточникЦельАссоциацияИмяФункцииГраницы
MemberTopicПервая ассоциацияtopicsCreatedchangeable0 to 1
Вторая ассоциация creatorchangeableОт 0 дo 1
TopicPostПервая ассоциацияpostsContainment, changeableОт 0 дo -1
Вторая ассоциацияtopicchangeableОт 0 дo 1
MemberPostПервая ассоциацияpostschangeableОт 0 дo -1
Вторая ассоциацияauthorchangeableОт 0 дo 1

Наконец, надо определить перечислимые типы для разных тем. Создайте новый перечислимый тип TopicCategory. Для Literals добавьте:

  • ANNOUNCEMENT, value = 0
  • GUEST_BOOK, value = 1
  • DISCUSSION, value = 2

Затем определите новый атрибут Topic с именем category и типом TopicCategory как changeable с границами 0-1. При желании на странице property можно изменить значение по умолчанию, но мы примем ANNOUNCEMENT.

Рисунок 2. Готовая модель класса UML
Готовая модель класса UML

Когда модель UML готова, как показано на рис.2, на следующем шаге создается модель EMF. Для этого создайте новый проект EMF (File > New > Project... > Eclipse Modeling Framework > EMF Project) и присвойте ему имя com.ibm.example.forum (оно станет основой имени модуля, так как мы следуем соглашениям об именах модулей Eclipse). На следующей странице выберите Load from an EMF core model и нажмите Next. Найдите в своей файловой системе и загрузите файл ecore, который должен автоматически заполнить имя модели генератора. На последней странице поставьте флажок рядом со своим пакетом и нажмите Finish. Это приведет к созданию модели EMF: forum.genmodel. Чтобы понять, что это такое, и как этим пользоваться, перейдите к разделу Применение сгенерированной модели EMF.

Создание модели EMF при помощи XML Schema

XSD не столь выразителен, как UML или аннотированный код Java. Например, он не в состоянии выражать двусторонние ссылки. Но так как по умолчанию процедура сериализации использует вашу схему, то это самый быстрый способ ее настройки. Если вам понадобится сгенерировать из своей модели очень специфический XML, XSD позволяет это сделать.

Листинг 1. Фрагмент forum.xsd
<xsd:simpleType name="TopicCategory">
   <xsd:restriction base="xsd:NCName">
      <xsd:enumeration value="Announcement"/>
      <xsd:enumeration value="GuestBook"/>
      <xsd:enumeration value="Discussion"/>
   </xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="Post">
   <xsd:sequence>
      <xsd:element name="comment" type="xsd:string"/>
      <xsd:element name="author" type="xsd:anyURI" ecore:reference="forum:Member"/>
      <xsd:element name="topic" type="xsd:anyURI" ecore:reference="forum:Topic"/>
   </xsd:sequence>
</xsd:complexType>

Из этого фрагмента видно, как установить перечислимый тип и как определить тип при помощи элементов и ссылок на другие типы. Для примера Forum мы используем только строковые атрибуты "xsd:string", но поддерживаются все простые типы Java. За более подробными сведениями обращайтесь к разделу Ресурсы.

Когда файл XSD готов, следующим шагом является создание модели EMF. Как и в случае модели UML, создайте новый проект EMF (File > New > Project... > Eclipse Modeling Framework > EMF Project) с именем com.ibm.example.forum (оно станет основой для имени модуля, так как мы следуем соглашениям об именах модулей Eclipse). На следующей странице выберите Load from an XML Schema и нажмите Next. Найдите в своей файловой системе и загрузите файл XSD, который должен автоматически заполнить имя модели генератора. На последней странице поставьте флажок рядом со своим пакетом и нажмите Finish. Это приведет к созданию модели EMF: forum.genmodel. Чтобы понять, что этот такое и как этим пользоваться, перейдите к разделу Применение сгенерированной модели EMF.

Создание модели EMF при помощи аннотированного кода Java

Чтобы определить модель EMF при помощи кода Java, воспользуемся функцией Interfaces для получения списка атрибутов каждого класса и отношений между ними. Так как этот список недостаточно полон и не содержит всей требуемой информации, в EMF применяются специальные теги JavaDoc. Каждый атрибут или класс, входящий в состав модели EMF, должен иметь в своем JavaDoc тег @model и может содержать список дополнительных атрибутов. Например, чтобы построить объектную модель в соответствии с рис.2, определение Forum должно выглядеть как в листинге 2.

Листинг 2. Аннотированный Forum.java
package com.ibm.example.forum;

import java.util.List;

/**
 * @model
 */
public interface Forum {
	
	/**
	 * @model type="Topic" containment="true"
	 */
	List getTopics();
	
	/**
	 * @model type="Member" containment="true"
	 */
	List getMembers();
	
	/**
	 * @model
	 */
	String getDescription();

}

Листинг 2 определяет объект с именем Forum, содержащий описание String и два дочерних списка Topic и Member. Оба они содержатся внутри Forum.

Для простых атрибутов, таких как description, тега @model достаточно, но для списков нужно указать также тип. Атрибут containment необязателен, но при наличии объекта он упорядочивается вместе со своим контейнером. Для упрощения этой процедуры нужно сделать так, чтобы все объекты прямо или косвенно содержались в Forum. В число некоторых других полезных опциональных атрибутов входят:

  • opposite (для двухсторонних свойств)
  • default (значение атрибута по умолчанию)
  • transient (атрибут не подлежит упорядочению)

Полный список приведен в руководстве пользователя EMF (см. раздел Ресурсы).

Единственное, на что еще надо обратить внимание, это то, что перечислимый тип определяется с помощью Класса, а не Интерфейса, как другие классы модели. Для примера в листинге 3 показано, как реализовать перечислимый тип TopicCategory.

Листинг 3. Перечислимый тип TopicCategory.java
package com.ibm.example.forum;

/**
 * @model
 */
public class TopicCategory{
	/**
	 * @model name="Announcement"
	 */
	public static final int ANNOUNCEMENT = 0;
	
	/**
	 * @model name="GuestBook"
	 */
	public static final int GUEST_BOOK = 1;
	
	/**
	 * @model name="Discussion"
	 */
	public static final int DISCUSSION = 2;
}

Чтобы завершить модель, сгенерируем три последних интерфейса следующим образом:

Таблица 3. Последние интерфейсы
ИнтерфейсМетодТеги модели
MemberList getPosts()type="Post" opposite="author"
List getTopicsCreated()type="Topic" opposite="creator"
String getName()
TopicList getPosts()type="Post" opposite="author"
Member getCreator()opposite="topicsCreated"
String getTitle()
TopicCategory getCategory()
PostMember getAuthoropposite="posts"
Topic getTopic()opposite="posts"
String getComment()

Когда определение модели будет готово, сгенерируйте модель EMF (File > New > Other > Eclipse Modeling Framework > EMF Models). Укажите com.ibm.example.forum/src/model в качестве родительского каталога и forum.genmodel в качестве имени файла (File name). На следующей странице выберите Load from annotated Java, затем поставьте флажок рядом с пакетом "forum". После этого нажмите Finish. Будет создана модель EMF forum.genmodel.


Применение сгенерированной модели EMF

Теперь в вашем рабочем пространстве должна быть сгенерирована модель EMF: forum.genmodel. Она содержит всю введенную в модель информацию. Откройте эту модель в редакторе по умолчанию (см. рис.3), затем откройте представление Properties и проверьте свойства каждого узла дерева модели. Все введенные ранее атрибуты можно редактировать, но есть также свойства для настройки генерации кода. Ради эксперимента попробуйте изменить такие свойства, как "Copyright Text" или "Generate Schema" и посмотрите, что произойдет.

Рисунок 3. Созданная модель EMF в редакторе по умолчанию
Созданная модель EMF в редакторе по умолчанию

Если вы внесли изменения в описание своей модели (UML, XSD, Annotated Java), то можете перезагрузить эту модель, щелкнув на ней правой кнопкой мыши в Package Explorer и выбрав Reload. Это приведет к синхронизации модели, сгенерированной EMF, с описанием модели. Свойства, измененные в сгенерированной модели, после перезагрузки не изменятся.


Генерация кода Java

Если вы удовлетворены описанием модели или просто хотите посмотреть, что все это значит, пора приступить к генерации кода. Щелкните правой кнопкой на корневом узле и выберите один из вариантов генерации кода: Model, Edit или Editor code. Выбор Generate Model приведет к созданию реализации на языке Java модели EMF в текущем проекте. Там будут:

  • com.ibm.example.forum -- Интерфейсы и Factory для создания классов Java
  • com.ibm.example.forum.impl -- Конкретное воплощение интерфейсов, определенных в com.ibm.example.forum
  • com.ibm.example.forum.util -- AdapterFactory

Выбор Generate Editor Code приведет к созданию проекта com.ibm.example.forum.edit. Он содержит всего один пакет com.ibm.example.forum.provider, который используется для управления способом отображения каждого объекта модели в редакторе. Выбор Generate Editor Code приведет к созданию редактора образцов модулей в проекте com.ibm.example.forum.editor, содержащего com.ibm.example.forum.presentation. Эти классы состоят из ряда простых редакторов JFace, взаимодействующих с вашей моделью.

Чтобы протестировать сгенерированный модуль, выполните Run > Run... > Run Time Workbench > New. Присвойте ему характерное имя и на вкладке модулей выберите launch with all workspace and enabled external plug-ins (запустить со всем рабочим пространством и включенными внешними модулями). В разделе Common выберите Display in favorites menu > Run и Launch in background. Сохраните эту конфигурацию и запустите программу.

Появится новое рабочее место Eclipse, и выбрав Help > About Eclipse Platform > Plug-in Details, можно убедиться, что модуль включен, как показано на рис. 4.

Рисунок 4. Детали модуля Forum
Детали модуля Forum

Чтобы проверить сгенерированный модуль, создайте новый проект Simple с именем Forum Demo и перейдите в New > Other... > Example EMF Model Creation Wizards > Forum Model. Присвойте ему имя файла sample.forum и выберите Forum в качестве Model Object. Откроется окно, в котором к корню можно добавлять новые элементы модели. Возможны несколько представлений: Selection, Parent, List, Tree, Table и TreeTable. Все они отображают одни и те же данные и синхронизированы с представлением Outline. Хотя все представления отображают опции меню, вызываемого правой кнопкой, New Sibling/New Child, я обнаружил, что некоторые из этих представлений неправильно реагируют на добавление дочерних элементов или элементов того же уровня. В этом случае воспользуйтесь представлением TableTree или создайте новые узлы в представлении Outline. Сгенерированный редактор модуля показан на рис.5.

Рисунок 5. Сгенерированный редактор модуля
Сгенерированный редактор модуля

Настройка сгенерированного кода

Все это хорошо, но этот сгенерированный код – только отправная точка для настоящих приложений. Чтобы соблюсти наши требования, нужно внести корректировки и настройки, от изменения реализации классов сгенерированной модели до расширения и настройки редакторов. К счастью, EMF позволяет произвести всю желаемую настройку и при регенерации ничего не потерять из внесенных нами изменений. Все, что нужно сделать, - это удалить тег @generated JavaDoc, а функция EMF jmerge гарантирует, что метод, атрибут или класс останутся нетронутыми.

Чтобы показать некоторые изменения, которые можно внести, выполним простой пример. В представлении Table сгенерированного редактора есть две колонки с одинаковыми значениями. Это не очень полезно. Чтобы несколько улучшить представление, изменим вторую колонку так, чтобы при выборе темы в ней отображался автор, а третья колонка пусть содержит номер публикации в этой теме.

Сначала добавим дополнительную колонку в представлении Table. Это делается в проекте com.ibm.example.forum.editor, как com.ibm.example.forum.presentation.ForumEditor в методе createPages(). Удалите тег @generated, чтобы сделать наше изменение постоянным, затем найдите раздел табличного представления. Измените код, как показано в листинге 4.

Листинг 4. Модифицированный метод createPages()
TableColumn selfColumn = new TableColumn(table, SWT.NONE);
layout.addColumnData(new ColumnWeightData(2, 100, true));
selfColumn.setText("Author");
selfColumn.setResizable(true);

TableColumn numberColumn = new TableColumn(table, SWT.NONE);
layout.addColumnData(new ColumnWeightData(4, 100, true));
numberColumn.setText("Number of Posts");
numberColumn.setResizable(true);

tableViewer.setColumnProperties(new String [] {"a", "b", "c"});

Добавится дополнительная колонка, но теперь во всех трех колонках отображаются одни и те же данные. Чтобы настроить данные для каждой колонки, нужно добавить реализации ITableItemLabelProvider. Откройте com.ibm.example.forum.provider.TopicItemProvider и добавьте в список реализаций ITableItemLabelProvider. Нужно добавить два метода, getColumnText(Object, int) и getColumnImage(Object, int), как показано в листинге 5.

Листинг 5. Дополнение TopicItemProvider
public String getColumnText(Object obj, int index) {
	if( index == 0 ){
		return getText(obj);
	}
	else if( index == 1 ) {
		return ((Topic)obj).getCreator().getNickname();
	} else if( index == 2 ) {
		return " + ((Topic)obj).getPosts().size();
	}
	return "unknown";
}
public Object getColumnImage(Object obj, int index) {
	return getImage( obj );
}

Наконец, нужно зарегистрировать этот источник. Отредактируйте конструктор com.ibm.example.forum.provider.ForumItemProviderAdapterFactory, добавив в список поддерживаемых типов ITableItemLabelProvider, как показано в листинге 6.

Листинг 6. Конструктор ForumItemProviderFactory
public ForumItemProviderAdapterFactory() {
	supportedTypes.add(ITableItemLabelProvider.class);
	supportedTypes.add(IStructuredItemContentProvider.class);
	supportedTypes.add(ITreeItemContentProvider.class);
	supportedTypes.add(IItemPropertySource.class);
	supportedTypes.add(IEditingDomainItemProvider.class);
	supportedTypes.add(IItemLabelProvider.class);
}

Теперь, когда мы выполним модуль и откроем табличное представление, мы увидим то, что изображено на рис.6. Обратите внимание, что для тех элементов, для которых ITableItemLabelProvider не реализован, во всех колонках будет отображаться один и тот же текст.

Рисунок 6. Модифицированный редактор Table
Modified Table editor

Управление моделью в Java

Сгенерированный код модели выглядит так же, как любой другой код Java, с несколькими полезными дополнениями. Имеется гибкий, специально настроенный API отражения, полезный для создания инструментов. Это методы eGet() и eSet(). Но они нас мало занимают, поэтому перейдем к более интересным вещам: как создать, сохранить и загрузить модель. Начнем с начала: с загрузки модели EMF.

Листинг 7. Загрузка модели Forum
// Register the XMI resource factory for the .forummodel extension
Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
Map m = reg.getExtensionToFactoryMap();
m.put("forummodel", new XMIResourceFactoryImpl());
ResourceSet resSet=new ResourceSetImpl();
Resource res = resSet.getResource(URI.createURI("model/forum.forummodel"),true);

Forum forum = (Forum)res.getContents().get(0);

В листинге 7 показано, как связать файлы с расширением forummodel в формате XMI, а затем применить ResourceSet из EMF для анализа и загрузки нашей модели форума. Мы знаем, что Forum будет лишь корневым элементом, так что можно предположить, что res.getContents().get(0) выдаст единственный объект Forum. В противном случае можно было бы извлечь Iterator из getContents().iterator() и проверить каждый элемент отдельно.

С другой стороны, можно создать новый Forum и программно наполнить его, как показано в листинге 8.

Листинг 8. Инициализация Forum
// initialize model and dependencies
ForumPackageImpl.init();
			
// retrieve the default Forum factory singleton
ForumFactory factory = ForumFactory.eINSTANCE; 
		
Forum forum = factory.createForum();
forum.setDescription("programmatic forum example");
		
Member adminMember = factory.createMember();
adminMember.setNickname("Administrator");
forum.getMembers().add( adminMember );

Topic noticeTopic = factory.createTopic();
noticeTopic.setTitle("Notices");
noticeTopic.setCategory(TopicCategory.ANNOUNCEMENT_LITERAL);
noticeTopic.setCreator(adminMember);
forum.getTopic().add( noticeTopic );

В данном примере сначала инициализируется пакет, а затем создается ForumFactory, которая и используется для создания всех подобъектов. После этого к ним можно обращаться как к любым стандартным модулям JavaBean. Однако так как мы декларировали двухстороннее отношение creator/topicsCreated между Topic и Member, при вызове noticeTopic.setCreator(adminMember) список topicsCreated элементов adminMember теперь содержит noticeTopic.

Когда модель EMF создана и настроена, ее легко сохранить в выбранном формате (см. листинг 9).

Листинг 9. Сохранение модели Forum
URI fileURI = URI.createFileURI("model/forum.ecore");
Resource resource = new XMIResourceFactoryImpl().createResource(fileURI);
resource.getContents().add( forum );
try {
	resource.save(Collections.EMPTY_MAP);
} catch (IOException e) {
	e.printStackTrace();
}

В этом примере мы присваиваем файлу, в который хотим сохранить URI.createFileURI(), имя и целевой формат. Так как мы сохраняем модель в XMI, мы используем XMIResourceFactoryImpl. Когда файл создан, добавляем в него все объекты модели, которые нужно оставить. В данном случае, так как каждый объект, за исключением Forum, содержится в другом классе, достаточно добавить его в корень, чтобы получить все дочерние объекты. Если у каких-то объектов нет отношения contains, их тоже нужно добавить явно посредством resource.getContents().add(). В противном случае вы получите нештатную ситуацию при вызове resource.save().


Заключение

Среда Eclipse Modeling Framework предоставляет инструменты разработки на основе модели. Она содержит элементы, необходимые для того, чтобы внимание разработчика было сосредоточено на самой модели, а не на деталях ее реализации. Главные области этого внимания: создание моделей, поддерживающих настройку, обратную связь, целостность ссылок и другие важные функции; создание настраиваемых редакторов моделей и сериализация по умолчанию. Как показано в примерах, генерация осуществляется легко и прямолинейно, и весь специализированный код поддерживает настройку. Отдельные инструменты, такие как сериализация или графический редактор, можно извлечь и использовать отдельно, но полный эффект достигается при их совместном использовании. Модели EMF уже применяются во многих успешных проектах, и их популярность продолжает расти.

Ресурсы

Научиться

Получить продукты и технологии

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Open source, Технология Java
ArticleID=402815
ArticleTitle=Моделирование при помощи среды Eclipse Modeling Framework: Часть 1. Создание моделей UML и генерация кода
publish-date=06262009