Управление проектами - статьи

         

Пример описания трансформации


Ранее был описан пример трансформации, предназначенной для преобразования платформо-независимой UML-модели классов в платформо-зависимую модель, ориентированную на технологию CORBA. Но этот пример трансформации был описан на естественном языке, а теперь попробуем задать его с помощью формального языка трансформации. В данной трансформации будут участвовать две модели с именами "source" и "target", первая из которых является исходной моделью, а вторая создаётся в процессе выполнения трансформации. Будет использоваться упрощённая метамодель классов UML, приведённая на .

Трансформация будет состоять из одного блока. Ниже показан заголовок этого блока и первое правило, соответствующее фразе "Для каждого класса из PIM следует создать класс реализации в PSM и связанный с ним класс-интерфейс" из неформального описания трансформации.

stage example_CORBA_transformation {

rule class_to_class { forall srcclass from source/classes make implclass in target/classes; implclass/name= srcclass /name+"_implementation"; implclass/stereotype="implementation" make interclass in target/classes; interclass/name=srcclass/name; interclass/stereotype="interface"; make d in target/associations; d/stereotype="realize"; make e in implclass/associations; e/base=d; e/cardinality=1; e/association_end_type="navigable"; include e in d/ends; make f in interclass/associations; f/base=d; f/cardinality=1; f/association_end_type="navigable"; include f in d/ends; e/otherend=f; f/otherend=e; }

Правило "class_to_class" для каждого класса исходной модели создаёт класс-интерфейс и класс-реализацию в генерируемой модели, а так же связь между ними. Далее напишем пару правил, соответствующих утверждениям "Все приватные атрибуты должны быть скопированы в соответствующие классы реализации" и "Публичные атрибуты следует также поместить в класс реализации, но уже как приватные; в интерфейс следует добавить методы для доступа и модификации этих атрибутов".


rule priv_attributes { forall srcclass from source/classes forall srcattrib from a/attributes where ((srcattrib /visibility="private") or (srcattrib /visibility="protected")) forall trgtclass from target/classes forall d from rules/class_to_class where ((d/srcclass=srcclass) and (d/implclass=trgtclass)) make trgtattrib in trgtclass/attributes; trgtattrib/name=srcattrib/name; trgtattrib/visibility=srcattrib/visibility; trgtattrib/type=srcattrib/type; }
rule pub_attributes { forall srcclass from source/classes forall srcattrib from a/attributes where srcattrib/visibility="public" forall implclass from target/classes forall interclass from target/classes forall d from rules/class_to_class where ((d/srcclass=srcclass) and (d/implclass=implclass) and (d/interclass=interclass)) make trgtattrib in implclass/attributes; trgtattrib/name=srcattrib/name; trgtattrib/visibility="private"; trgtattrib/type=srcattrib/type; make getoperation in interclass/operations; getoperation/name="get_"+srcattrib/name; getoperation/type=srcattrib/type; make setoperation in interclass/operations; setoperation/name="set_"+srcattrib/name; make h in setoperation/parameters; h/type=srcattrib/type; }
В этих правилах использована трансформационная связь, образованная применением правила "class_to_class". Благодаря этой связи возможно определить класс-интерфейс и реализацию, порождённые заданным классом исходной модели. Следующее правило из неформального описания - "Публичные операции класса копируются в интерфейс, приватные - в класс реализации", оно описывается с помощью нескольких формальных правил.
rule methods1 { forall srcclass from source/classes forall srcoper from a/operations where srcoper/visibility="public" forall trgtclass from target/classes forall d from rules/class_to_class where ((d/srcclass=srcclass) and (d/interclass=trgtclass)) make trgtoper in trgtclass/operations; trgtoper/name=srcoper/name; trgtoper/type=srcoper/type; trgtoper/visibility=srcoper/visibility; }


rule methods1a { forall a from rules/methods1 forall b from a/srcoper/parameters make c in a/trgtoper/parameters; c/name=b/name; c/type=b/type; }
rule methods2 { forall srcclass from source/classes forall srcoper from a/operations where srcoper/visibility=("private" or "protected") forall trgtclass from target/classes forall d from rules/class_to_class where ((d/srcclass=srcclass) and (d/implclass=trgtclass)) make trgtoper in trgtclass/operations; trgtoper/name=srcoper/name; trgtoper/type=srcoper/type; trgtoper/visibility=srcoper/visibility; }
rule methods2a { forall a from rules/methods2 forall b from a/srcoper/parameters make c in a/trgtoper/parameters; c/name=b/name; c/type=b/type; }
Правила с именами methods1 и methods2 отображают публичные и приватные операции соответственно, а вспомогательные правила methods1a и methods2a нужны для копирования параметров операций. Далее формально зададим утверждение "Ассоциации "один к одному" и "многие к одному" преобразуются в атрибут - объектную ссылку", а так же "Связи-обобщения преобразуются в аналогичные связи-обобщения между классами-интерфейсами".
rule associations_single { forall srcclass from source/classes forall assoc from srcclass/associations where assoc/base/association_type="navigation" where ((assoc/otherEnd/cardinality="1") or (assoc/otherEnd/cardinality="0..1")) where assoc/otherEnd/association_end_type="navigable" forall d from rules/class_to_class where d/srcclass=srcclass forall e from rules/class_to_class where e/srcclass=assoc/otherEnd/class make objptr in d/implclass/attributes; objptr/type=e/interclass/name+"_ptr"; objptr/name=assoc/otherEnd/name; objptr/visibility="private"; }
rule association_generalization { forall srcclass from source/classes forall srcassoc from a/associations where srcassoc/base/association_type="generalization" where srcassoc/otherEnd/association_end_type="navigable" forall c from rules/class_to_class where c/srcclass=srcclass forall d from rules/class_to_class where d/srcclass=srcassoc/otherEnd/class make trgtassoc in target/associations; trgtassoc/association_type="generalization"; trgtassoc/stereotype=srcassoc/base/stereotype; trgassoc/name=srcassoc/base/name; make f in c/interclass/associations; f/name=srcassoc/name; f/cardinality=srcassoc/cardinality; f/association_end_type=srcassoc/association_end_type; include f in trgtassoc/ends; make g in d/interclass/associations; g/name=srcassoc/otherEnd/name; g/cardinality=srcassoc/otherEnd/cardinality; g/association_end_type=srcassoc/otherend/association_end_type; include g in trgtassoc/ends; f/otherend=g; g/otherend=f; }
И, наконец, последнее правило соответствует утверждению "Интерфейсы исходной модели и их связи копируются в генерируемую модель без создания классов-реализаций".
rule interface_mapping { forall a from rules/class_to_class where a/srcclass/stereotype="interface" delete a/implclass; } }
На самом деле данное правило просто удаляет лишние классы реализации, созданные первым правилом. Последняя фигурная скобка обозначает окончание блока трансформации. Итак, полученное описание трансформации формально определяет те преобразования модели, которые необходимы при переходе к PSM, основанной на CORBA и которые были заданы на естественном языке в начале статьи. В результате выполнения этого описания трансформации на какой-либо модели классов будет получена платформо-зависимая модель "target" и совокупность связей между этой моделью и исходной.

Содержание раздела