Расширение преобразования UML-to-Java 5 при помощи Rational Software Architect Version 7

IBM Rational Software Architect - это инструментальное средство для архитекторов и проектировщиков программных систем. Оно объединяет UML (Unified Modeling Language) и инструментальные средства разработки, включая редактор исходного кода, компилятор и отладчик. Для этого Rational Software Architect использует преобразование UML-to-Java™ 5, превращая UML-модели в классы, интерфейсы и перечисления в исходном коде Java 5. Хотя функциональность такого преобразования является полной, есть пользователи, которые возможно захотят расширить это преобразование для включения специализированных элементов или соглашений, а также для поддержки созданного ими расширения DSL (Domain Specific-Language). В данной статье на простом примере продемонстрированы базовые элементы расширения этого преобразования.

О функциональности преобразования Java 5 в Rational Software Architect

IBM Rational Software Architect имеет несколько предопределенных преобразований и некоторые из них преобразуют UML-модель в исходный код. В Version 7 появилось преобразование, использующее функциональные возможности Java 5. Как и его предшественники, это преобразование может быть расширено. В данной статье в пошаговом режиме рассматривается процесс создания простого примера, демонстрирующего базовые возможности этой функциональности.

В данном случае, как и для большинства функциональных возможностей Rational Software Architect, используются обычные механизмы расширения Eclipse - создание плагина и реализация специализированных точек расширения. Данная статья не предназначена для обсуждения общих вопросов разработки плагинов (ссылки на рекомендованные статьи и примеры приведены в разделе "Ресурсы"). Она подразумевает наличие достаточных навыков в разработке плагинов, необходимых для создания и тестирования расширения преобразования.

Рисунок 1. Общая структура преобразования
Рисунок 1. Общая структура преобразования

Преобразование начинается с элемента UML-модели, пакета, класса, интерфейса или перечисления, в зависимости от того, что было выбрано при активизации преобразования. Преобразование будет работать с выбранным элементом (или с целой моделью, если элемент не выбран) и со всеми элементами, которые он содержит. Это дает автору расширения преобразования много возможностей для реализации специализированной логики в общем процессе преобразования. Расширение предназначается только для одной части общего преобразования. Полный список назначений приведен в приложении (см. раздел "Загрузка").

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

Мы выполним следующие действия:

  1. Создадим новый проект плагина для расширения преобразования. Этот проект может быть скомбинирован с другими расширениями, однако для упрощения примера мы создадим новый проект с нуля.
  2. Добавим набор необходимых зависимых плагинов. Эти плагины определяют точку расширения, реализуемую нами, и обеспечивают API, которые понадобятся для активизации нашего расширения.
  3. Определим точку расширения в дескрипторе плагина, который определяет расширяемое преобразование и точку в нем, которую мы хотим использовать.
  4. Предоставим Java-реализацию правила класса, которое будет активироваться каждый раз, когда преобразование встретит элемент с указанным нами типом.
  5. Протестируем преобразование путем активизации рабочей среды времени исполнения и запуска преобразования UML-to-Java 5.

Шаг 1. Создание и настройка нового проекта плагина

Расширение преобразования начинается с нового проекта плагина:

  1. Выберите меню File > New > Project и Plug-in Project в списке типов проектов. Нажмите кнопку Next.
  2. На первой странице мастера New Plug-In Project введите корректное имя проекта. Соглашением для плагинов Eclipse является использование URI-домена, аналогичного показанному на рисунке 2.

Рисунок 2. Мастер New Plug-in Project
Рисунок 2. Мастер New Plug-in Project

  1. На второй странице (рисунок 3) измените значение по умолчанию в поле Plug-in Name; остальные значения по умолчанию являются приемлемыми.

Рисунок 3. Страница Properties мастера New Plug-in Project
Рисунок 3. Страница Properties мастера New Plug-in Project

На последней странице не нужно выбирать шаблон плагина, поскольку для расширений преобразования нет шаблонов; они есть только для новых полных преобразований.

Рисунок 4. Последняя страница мастера New Plug-in Project
Рисунок 4. Последняя страница мастера New Plug-in Project

  1. Снимите флажок с варианта template и нажмите кнопку Finish (рисунок 4).

После завершения работы мастер создаст новый проект плагина и откроет страницу Overview дескриптора проекта (рисунок 5).

Рисунок 5. Структура нового проекта
Рисунок 5. Структура нового проекта

Шаг 2. Добавление необходимых зависимых плагинов

Следующий шаг - добавить несколько плагинов в качестве зависимостей. Эти плагины содержат определения точек расширения для реализации дополнительных API, которые будут использоваться при реализации расширения.

  1. Перейдите в закладку Dependencies (внизу этого редактора) и добавьте следующие плагины в качестве зависимостей:
    • com.ibm.xtools.modeler
    • com.ibm.xtools.transform.core
    • com.ibm.xtools.transform.uml2.java5
    • org.eclipse.jdt.core
  2. Убедитесь в том, что все плагины были добавлены. Результат должен выглядеть примерно так, как показано на рисунке 6.

Рисунок 6. Зависимые плагины
Рисунок 6. Зависимые плагины

Шаг 3. Определение и реализация расширения

Следующий шаг - объявить о том, что мы собираемся предоставить реализацию для одной или нескольких точек расширения.

Перейдите в закладку Extensions и нажмите кнопку Add для добавления нового расширения. Отобразится диалоговое окно, показанное на рисунке 7. Введите следующую точку расширения: com.ibm.xtools.transform.core.transformationExtensions. После ее обнаружения выберите ее и нажмите кнопку Finish.

Рисунок 7. Диалоговое окно New Extension
Рисунок 7. Диалоговое окно New Extension

  1. Необходимо предоставить дополнительную информацию в определении точки расширения. Эти значения могут быть введены через пользовательский интерфейс закладки Extension. Однако большинство пользователей считает, что легче просто изменить XML-код файла plugin.xml. Этот файл создается, когда расширение определяется в первый раз (до этого он не нужен, поэтому не создается мастером New Project).
  2. Перейдите в закладку plugin.xml. Вы увидите исходный XML-файл, который можно редактировать.
  3. Добавьте детали, приведенные в листинге 1, для точки расширения.

Листинг 1. Объявление расширения

                
     <extension point="com.ibm.xtools.transform.core.transformationExtensions" >
   
      <TransformationExtension version="1.0.0"
            name="My UML to Java5 Transformation Extensions"
            enabled="true"
            targetTransformation=
            "com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform"
            id="com.ibm.rsa.java5.extension.sample.transformationExtensions.id">

         <RuleDefinition
         	name="Javadoc Keyword Rule"
         	class="com.ibm.rsa.java5.extension.sample.ClassKeywordJavadocRule"
         	id="com.ibm.rsa.java5.extension.sample.ClassKeywordJavadocRule.id"/>

         <ExtendTransform
			targetTransform=
			"com.ibm.xtools.transform.uml2.java5.internal.ClassTransform">
            <AddRule id="com.ibm.rsa.java5.extension.sample.ClassKeywordJavadocRule.id"/>
         </ExtendTransform>

      </TransformationExtension>
   
   </extension>
      

Тело элемента extension определяется провайдером точки расширения. В данном случае это компонент Rational Software Architect Core Transformation. Это расширение ожидает дочерние элементы TransformationExtension (по одному на каждый тип расширяемого преобразования). Каждый из этих элементов определяет, какое преобразование расширяется.

  1. Для данного простого примера укажите targetTransformation с ID com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform.
  2. Предоставьте соответствующие значения для ID: номер версии, имя и значение Boolean для enabled.

Каждое расширение преобразования определяет как дочерние элементы определение правила, указывающее класс, который реализует интерфейс правила. Этот класс выполняет основную часть работы по преобразованию. Он определяется как отдельный элемент, поскольку один класс может принимать участие в нескольких частях преобразования (например, класс, свойство и операция).

После определения все правила соответствуют частям преобразования, в которых будут принимать участие с элементами ExtendTransform. Этот элемент определяет часть преобразования, в котором будет принимать участие правило. В данном примере мы хотим участвовать в расширении при каждом преобразовании нового класса, и значением targetTransform должно быть com.ibm.xtools.transform.uml2.java5.internal.ClassTransform. Полный список ID целевых преобразований содержится в приложении, которое вы можете загрузить по ссылке, приведенной в данной статье (см. раздел "Ресурсы").

Поскольку в любой конкретной части преобразования может участвовать более одного правила, они собираются как дочерние элементы элемента ExtendTransform. Здесь мы определяем только одно правило.

Примечание:
ID правила в элементе RuleDefinition должно соответствовать ID элемента AddRule.

Шаг 4. Предоставление Java-реализации правила класса

После завершения редактирования данного файла сохраните его. Вы должны заметить в файле plugin.xml маленькую пиктограмму ошибки в левом поле рядом со строкой, указывающей класс реализации. Это говорит о том, что файл не найден в проекте.

  1. Можно выполнить двойной щелок левой кнопкой мыши на этой пиктограмме и выбрать запрос Create a new class. При этом активируется мастер New Class, который можно использовать для создания файла класса. Можно также вручную создать класс через меню File > New. Какой бы способ создания Java-классов в Eclipse вы ни предпочли, создайте его в назначенном пакете и с корректным именем.
  2. Для максимального упрощения реализации расширьте класс интегрированной среды преобразований Rational Software Architect com.ibm.xtools.transform.uml2.imple.internal.java5.ClassRule. Используя этот класс в качестве суперкласса, нужно переопределить только три метода:
    • canAccept
    • createTarget
    • isSourceConsumed

Каждый из этих методов принимает объект контекста преобразования, к которому можно выполнять запросы на получение доступа к исходному и целевому объектам. Используя данную информацию, можно решить, выполнять дальнейшую обработку конкретного класса (canAccept), или дальнейшая обработка этого класса должна быть прервана (isSourceConsumed). Если это расширение принимает контекст, тогда для реального участия в преобразовании используется метод createTarget().

  1. Для данного простого расширения преобразования возвратите False в методе isSourceConsumed для указания того, что дальнейшая обработка должна продолжаться, а расширение вовсе не означает, что вся работа по преобразованию данного конкретного элемента была завершена.
  2. Укажите, что мы может принимать конкретный класс, когда определено как минимум одно ключевое слово. Если ключевых слов нет, нам нечего делать, поэтому укажем, что это нам не интересно. Мы можем принимать исходный UML-класс через контекст преобразования, который передается как аргумент. Метод getSource() контекста должен возвращать ссылку на UML-класс, поскольку мы указали в точке расширения, что интересуемся только Class transforms.
  3. Введите исходный объект в UML-класс и получите список ключевых слов. Если список пуст, возвратите False.

Если ключевые слова есть, мы можем ожидать вызова метода createTarget(). Именно здесь мы вносим наш вклад в преобразование.

Листинг 2. Java-реализация правила класса

                
package com.ibm.rsa.java5.extension.sample;

import java.util.Iterator;
import java.util.List;

import org.eclipse.emf.common.util.EList;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.TagElement;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.uml2.uml.Class;

import com.ibm.xtools.transform.core.ITransformContext;
import com.ibm.xtools.transform.uml2.impl.internal.java5.ClassRule;

public class ClassKeywordJavadocRule extends ClassRule  {

	protected Object createTarget(ITransformContext context) {
		TypeDeclaration target = (TypeDeclaration) context.getTarget();
		Javadoc javadoc = target.getJavadoc();
		List tags = javadoc.tags();

		AST ast = target.getAST();
		
		Class umlCls = (Class) context.getSource();
		EList keywords = umlCls.getKeywords();
		
		for (Iterator iter = keywords.iterator(); iter.hasNext();) {
			String keyword = (String) iter.next();
			TagElement tag = ast.newTagElement();
			tag.setTagName("@" + keyword);
			tags.add(tag);
		}
		return target;
	}

	public boolean isSourceConsumed(ITransformContext context) {
		return false;
	}

	public boolean canAccept(ITransformContext context) {
		Class umlCls = (Class) context.getSource();
		return umlCls.getKeywords().size()>0;
	}
	
}

Первое, что обычно делают разработчики при реализации метода createTarget(), - это обращение к исходному и целевому объектам для данной части преобразования. Поскольку мы определили, что это расширение активизируется при обработке преобразованием UML-класса, то можем смело ввести целевой объект в объект Abstract Syntax Tree (AST) TypeDeclaration. Проект Eclipse Java Developer Tools (JDT) предоставляет все API для манипулирования исходным Java-кодом. AST - это объектная модель, анализирующая синтаксис исходного кода для Eclipse. При активизации этого метода, интегрированной средой преобразования создается новый объект TypeDeclaration. Нужно отметить, что если есть какой-нибудь существующий Java-код, он не будет доступен в целевом объекте. Объединение сгенерированного кода с существующим происходит после преобразования всех элементов модели.

Подробное обсуждение AST выходит за рамки данной статьи, но нужно отметить, что когда расширение нуждается в добавлении новых элементов к сгенерированному исходному коду, это делается путем вызова методов AST-объектов. В нашем простом примере мы просто добавим новый тег Javadoc в комментарии Javadoc определения класса. Javadoc - это тип объектов в AST, получаемый из объекта TypeDeclaration.

  1. Из Javadoc object получите список тегов, формирующих этот Javadoc. Можно добавить (или удалить) теги из сгенерированного исходного кода.
  2. Для определения того, какой тег добавлять, обратитесь к исходному объекту из контекста преобразования и выполните приведение его типа в UML-класс. Из данного объекта мы получаем список ключевых слов (аналогично тому, как делали это при реализации метода canAccept()).
  3. Имея такой список, выполните итерацию по ключевым словам и создайте новый TagElement для каждого из них.
  4. Установите имя тега в значение ключевого слова (начиная с символа @).
  5. Наконец, добавьте новый тег в список тегов для класса Javadocs.

Метод должен возвратить целевой объект. Обычно это тот же объект, который был передан как назначение. На этом завершается процесс создания и реализации расширения преобразования.

Шаг 5. Тестирование расширения

Теперь после определения и реализации расширения пора приступить к его тестированию. Это делается путем создания новой отладочной конфигурации, которая открывает новую рабочую среду времени исполнения (runtime workbench).

  1. Для создания этой конфигурации выберите Run > Debug в главном меню.
  2. В диалоговом окне создайте новую конфигурацию приложения Eclipse и назовите ее соответствующим образом.

Совет:
Можно изменить месторасположение рабочей области, что является хорошей идеей для устранения влияния на существующую рабочую область.

  1. Оставьте остальные настройки в значениях по умолчанию (рисунок 8).

Рисунок 8. Новая отладочная конфигурация
Рисунок 8. Новая отладочная конфигурация

  1. После завершения редактирования конфигурации нажмите кнопку Debug для запуска нового экземпляра Eclipse. Этот экземпляр будет иметь в качестве плагина расширение преобразования, которое мы только что создали.
  2. Для тестирования расширения необходимо в новом экземпляре Eclipse создать новый Java-проект и UML-модель в этом проекте.
  3. В UML-модели создайте тестовый пакет и класс и включите в него несколько атрибутов или операций. Полученная рабочая область должна выглядеть примерно так, как показано на рисунке 9.

Рисунок 9. Тестовый проект в рабочей среде времени исполнения
Рисунок 9. Тестовый проект в рабочей среде времени исполнения

Затем необходимо добавить в класс ключевое слово, поскольку ваше расширение будет работать только с классом, в котором определено ключевое слово.

  1. Выберите класс в закладке Stereotypes в виде Properties.
  2. Введите текст в поле Keywords (рисунок 10).

Рисунок 10. Настройка свойства keywords
Рисунок 10. Настройка свойства keywords

После установки тестового проекта и модели необходимо создать новую конфигурацию преобразования, которая определяет основные параметры преобразования UML-to-Java 5.

  1. Выберите File > New в основном меню.
  2. Под категорией Transformations выберите Transformation Configuration и нажмите кнопку Next (рисунок 11).

Рисунок 11. Создание новой конфигурации преобразования
Рисунок 11. Создание новой конфигурации преобразования

  1. Существует много типов преобразования, входящих в Rational Software Architect. Выберите преобразование UML-to-Java 5 (рисунок 12), поскольку именно для него мы создали расширение.
  2. Назначьте подходящее имя. Оно будет использоваться как имя файла конфигурации в Java-проекте.

Рисунок 12. Выбор преобразования
Рисунок 12. Выбор преобразования

  1. Первое, что необходимо указать в конфигурации преобразования - исходная модель и целевой проект:
    • Выберите UML-модель, поскольку она появляется в виртуальной папке Models, а не является реальным .emx-файлом.
    • Выберите назначение, указав сам Java-проект (рисунок 13).

Рисунок 13. Настройка источника и назначения преобразования
Рисунок 13. Настройка источника и назначения преобразования

  1. При желании можете отключить автоматическое генерирование методов get и set на следующей странице настройки конфигурации (рисунок 14) и поэкспериментировать с другими параметрами на оставшихся страницах. Однако для данного простого теста достаточно принять значения по умолчанию и нажать кнопку Finish.

Рисунок 14. Параметры конфигурации преобразования
Рисунок 14. Параметры конфигурации преобразования

Теперь после создания конфигурации ее можно активизировать. Для работы с данным проектом ее не нужно создавать повторно.

  1. Для активизации преобразования и вашего расширения выберите класс в диаграмме, активизируйте всплывающее меню и выберите Transform > My UML to Java5 Transform Test.tc > UML to Java V5.0 (Рисунок 15).

Рисунок 15. Активизация преобразования
Рисунок 15. Активизация преобразования

На рисунке 16 показаны результаты преобразования. Вы можете увидеть, что тег Javadoc, соответствующий добавленному вами значению ключевого слова, включен в Javadocs класса.

Рисунок 16. Результаты генерирования кода
Рисунок 16. Результаты генерирования кода

Заключение

Этот простой пример расширения преобразования UML-to-Java 5 демонстрирует базовый механизм создания расширений. Реальные расширения в своем большинстве наверняка будут более интеллектуальными, используя информацию в модели и выполняя более интересные изменения в сгенерированном коде или даже добавляя сопутствующие артефакты в исходный код. Важным заключением, которое можно сделать по данной статье, является то, что создание расширений существующих преобразований имеет большой смысл, когда нужно использовать возможности всего сделанного ранее и просто внести небольшие изменения или добавления в выходные данные. Наличие одного общего преобразования, генерирующего код, а также других артефактов (например, дескрипторы развертывания или сопутствующие файлы) также упрощает процесс разработки, поскольку нужно выполнить только одно, а не много преобразований.


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=10321