IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Rational  >

基于RSA模型转换框架的开发

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 初级

何蕾 孙瑛霖,, IBM 中国软件开发实验室 SOA设计中心 高级软件工程师, IBM

2005 年 9 月 01 日

本文首先介绍模型转换的基本概念,然后介绍RSA模型转换框架,之后本文以两个具体的例子介绍如何在RSA开发平台中以模型转换框架为基础创建和扩展模型转换。

1 内容简介

模型转换框架(Model Transformation Framework)是IBM最新开发平台RSA(Rational Software Architect)中的重要组成部分,其主要功能是在模型驱动的开发过程中,为实现各种模型之间的转换提供基础平台的支持。基于这个框架,能够很容易地实现模型之间的转换程序,以及扩展已有的转换。

本文首先介绍模型转换的基本概念,然后介绍RSA模型转换框架,之后本文以两个具体的例子介绍如何在RSA开发平台中以模型转换框架为基础创建和扩展模型转换。





回页首


2 模型转换

MDA(Model Driven Architecture,模型驱动的体系结构)和MDD(Model Driven Development,模型驱动的开发)是当今软件领域最热门的话题。相比于传统的以代码为中心的开发模式,MDA和MDD则是以模型为中心,在开发的各个阶段,都使用模型来描述系统特征。

模型转换贯穿于MDD的全过程。系统开发初期,为了刻画系统特征,一般会创建系统的分析模型。分析模型是一个比较粗糙的模型,相当于草图的作用,只用于辅助分析。随着系统的特征越来越清晰,系统的设计模型会慢慢形成。设计模型能够比较精确地描述系统,是系统实现的基础。从设计模型可以很容易地导出系统的实现模型。实现模型包括具体的代码、脚本、配置文件等等。这是一个自顶向下、逐层细化的过程,从高层的抽象模型开始,经过一系列的模型转换,最终生成底层的系统实现。


图1 模型转换
图1 模型转换

由此可见,模型转换在模型驱动的开发和设计中起着非常重要的作用。





回页首


3 RSA模型转换框架

RSA(Rational Software Architect)是IBM的新一代软件开发平台,代号为Atlantic。RSA基于开放/可扩展的Eclipse 3.0构建,全面支持UML 2.0标准和模型驱动的开发方法。RSA为开发当今日益复杂的应用系统提供了一个强大的的开发环境,整合了UML建模、J2EE、XML、web services、C++开发工具以及RUP过程指南等诸多功能,是软件架构师/开发人员的首选工具。

为了支持模型驱动开发过程中各种模型之间的转换,RSA提供了一个功能强大、易于扩展的模型转换框架(Model Transformation Framework),该框架是一个基于规则的执行引擎,基于该框架,可以很方便地定义模型转换规则,实现各种模型之间的转换。RSA模型转换框架实现了模型转换的注册和配置管理,提供了统一的运行界面,以及各种开发向导。

RSA预装有一些常用的模型转换,包括UML2JAVA、UML2CPP、UML2EJB,这三个转换分别以UML模型为输入,生成对应的Java程序、CPP程序和EJB。关于如何使用RSA预装的模型转换,请读者参阅RSA的相关文档。

下面简单介绍RSA模型转换相关的一些概念:

  • Transformation(转换):以源模型对象为输入,目标模型对象为输出,实现模型之间的转换。每个转换由若干条转换规则组成。
  • Rule(转换规则):以源模型对象中某部分为输入,目标模型对象的对应部分为输出,实现了功能逻辑上相对独立的一部分转换任务。
  • Transformation Context(转换上下文):转换上下文是转换过程中转换规则之间共享数据的容器。在转换的执行过程中,转换上下文会在规则的实现之间传递,每一个规则可以向上下文中存放需要共享的数据,也可以从中获取所需的数据。
  • Transformation UI:模型转换框架会为每个转换提供一个默认的配置管理界面,让用户指定源模型,目标模型,以及所需的一些转换属性。如果需要定制更加复杂的界面元素,则需要模型转换的开发人员对默认的界面加以扩展。

至此,读者应该已经对RSA模型转换框架有了总体的了解,本文余下部分将结合具体的例子,介绍如何在RSA中基于模型转换框架开发新的模型转换和扩展已有的模型转换。





回页首


4 基于RSA模型转换框架的开发

本节以一个具体的模型转换为例,介绍如何在RSA中基于模型转换框架开发新的模型转换。这个转换名为Model2Text,接受的输入为UML模型中的Class、Package,或者Model,如果输入为Class,则遍历类的属性、方法、参数,将这些信息输出到控制台,如果输入为package或者model,则遍历package和model下面的每一个类,将类的信息打印到控制台。

4.1 创建新的插件工程

通过新建工程向导创建一个插件工程。由于模型转换框架是作为eclipse插件集成在RSA中,因此模型转换工程也必须是一个eclipse插件工程,这样才能够使用转换框架提供的组件。

4.2 添加TransformationProviders扩展点

为了创建一个新的模型转换,需要从TransformationProvider扩展点进行扩展。首先添加所需的插件:


图2 开发模型转换所需的插件
图2 开发模型转换所需的插件

然后添加TransformationProviders扩展点,该扩展点的ID为com.ibm.xtools.transform.core.transformationProviders。

4.3 创建模型转换的入口:TransformationProvider

从TransformationProviders扩展点扩展,添加TransformationProvider:


图3 创建TransformationProvider
图3 创建TransformationProvider

添加TransformationProvider之后需要创建对应的实现类,这个类需要继承自模型转换框架提供的接口com.ibm.xtools.transform.core.AbstractTransformationProvider,是模型转换框架执行引擎调用模型转换的入口点,主要提供两个方法:

createTransformation创建模型转换的实例,返回给调用引擎
validateContext验证模型转换的执行上下文,从上下文中可以获取源模型和目标容器,进行验证。验证的结果会反映在模型转换的配置管理界面上。本例验证源模型是否Class、Package或者Model。

4.4 创建Transformation

本例的Model-to-Text转换在plug-in.xml中定义如下:


<Transformation
 version="1.0"
 name="%Transformation.name.classtotext.console"
transformGUI="com.ibm.xtools.transform.samples.modeltotext.TransformGUI"
 keywords="%Transformation.keywords.classtotext.console"
 author="%Transformation.author"
 groupPath="%Transformation.groupPath"
 sourceModelType="UML2"
description="%Transformation.description.classtotext.console"
 document="doc/classToTextToConsole.html"
 targetModelType="None"
id="com.ibm.xtools.transform.samples.classtotext.console.root">
</Transformation>

Transformation的主要属性:

Id注册在模型转换框架中唯一的id。可以通过这个id引用这个模型转换
name模型转换的名字,也即最终显示在Transformation弹出菜单中菜单项的内容
sourceModelType源模型的类型,如UML2、Resource等等。本例选择UML2。
targetModelType目标模型的类型,由于本例是将源模型中类的信息输出到控制台,所以选择None
transformGUI自行定制的配置界面的实现类名。如果不指定,则转换框架会提供一个缺省的界面
document该模型转换相关文档存放的位置

4.5 为transformation定义规则

每个模型转换都由若干转换规则组成,每条规则实现了逻辑上相对独立的一部分转换功能,若干条规则组合在一起实现整个转换功能。转换规则的实现类应该实现模型转换框架中提供的com.ibm.xtools.transform.core.AbstractRule接口,一般需要实现如下两个方法:

createTarget从转换上下文对象中获取源模型对象,生成目标模型中相应的对象
canAccept该方法会在执行转换规则之前调用,验证源模型,通过验证则调用规则,否则执行引擎会忽略该规则。

本例定义了4条转换规则:ClassRule、OperationRule、ParameterRule、PropertyRule,分别操作源模型中的类、操作、参数和属性对象,并输出信息到控制台。

转换规则需要在模型转换实例初始化的时候添加:


UML2Package uml2 = UML2Package.eINSTANCE;
addByKind(uml2.getClass_(), new ClassRule());
addByKind(uml2.getProperty(), new PropertyRule());
addByKind(uml2.getOperation(), new OperationRule());
addByKind(uml2.getParameter(), new ParameterRule());

这段代码将4条规则添加到模型转换中,并指定每条规则所能够接收的源模型对象的类型。

4.6 运行测试

至此,Model-to-Text转换已经编写完成,下面开始运行测试。由于模型转换本身是一个Eclipse插件工程,所以必须从RSA中再启动一个RSA Workbench实例,将Model-to-Text插件加载运行。

workbench启动之后,切换到modeling视图,选择Modeling菜单->Transform->Configure Transformations,打开模型转换配置界面,可以看到,Model-to-Text转换已经注册到模型转换框架中:


图4 Model-to-Text转换已经注册到模型转换框架中
图4 Model-to-Text转换已经注册到模型转换框架中

创建一个UML模型,新建一个类Account,并添加一些属性和操作:


图5 Account类
图5 Account类

然后在Account类上右击,从弹出菜单中选择Transformations -> Class to Text -> console,开始执行转换。该转换接收Account类作为源模型对象,将Account类的信息输出到控制台:


Class: Account
	Attribute: id
	Attribute: balance
	Operation: setID
		Parameter: id
	Operation: getID
		Parameter: ReturnResult
	Operation: setBalance
		Parameter: balance
	Operation: getBalance
		Parameter: ReturnResult

在模型编辑器中创建一个Component,作为输入再次执行Model-to-Text转换,由于Component不能通过源模型认证,因此模型转换框架在配置界面上报告错误:


图6 源模型对象验证错误
图6 源模型对象验证错误

如果需要对模型转换进行调试,则需要以Debug模式启动RSA Workbench,之后便可以在源代码中设置断点,进行调试。





回页首


5 扩展模型转换

RSA模型转换框架提供了良好的可扩展性,用户可以根据具体的应用需求,在已有模型转换的基础上增加一些转换规则进行扩展。例如,RSA预装的UML2Java转换是一种基础性的转换,在实际应用中,可以对其进行扩展,在生成的Java代码中增加一些版权声明。

一般来说,一个模型转换通常会根据功能划分成若干个转换,每个转换由若干规则组成,实现一部分独立的功能,例如,UML2JAVA总的转换程序为UML2JavaTransform,按照转换的不同阶段,划分为PropertyTransform,OperationTransform等等,在这些转换之间,通过转换上下文共享数据。这样,在对其进行扩展的时候,需要根据具体的需要,在某些阶段的模型转换中增加转换规则,并通过转换上下文共享数据。

对于一个已有的模型转换,可能存在很多扩展,在转换执行的时候,所有的这些扩展转换规则都会被加载执行,那么用户如何只选择执行他们需要的扩展规则,而忽略掉其他扩展规则呢?在模型转换的开发过程中,一般使用UML Profile来解决这个问题。在扩展模型转换的时候,开发者往往会提供一个UML Profile,用户使用这个profile中定义的stereotype对需要执行扩展转换规则的源模型对象作标记,扩展转换规则会根据特定的stereotype来过滤源模型对象,选择执行还是不执行。

本节以一个具体的例子来介绍如何基于RSA模型转换框架扩展系统已有的模型转换。本例将扩展UML2JAVA转换,扩展之后,用户对UML模型执行UML2JAVA的时候,扩展规则会为Class中的属性添加Get和Set方法,对于只读属性,只添加Get方法。这个扩展的实现包括两条扩展规则和一个UML profile,profile提供了一个stereotype,用户在源模型中对需要生成get和set方法的属性上应用这个stereotype。DefineGetterSetterRule添加到UML2JAVA转换中的PropertyTransform,用于收集源模型中需要生成get和set方法的属性,并存放到转换上下文中,CreateGetterSetterRule添加到ClassTransform中,该规则从转换上下文中获取DefineGetterSetterRule之前设置的属性信息,创建对应的get和set方法,如果属性只读,则只创建get方法。

下面介绍主要的开发步骤:

5.1 新建插件工程

模型转换的扩展也必须实现为Eclipse的插件。

5.2 创建UML Profile

关于如何创建UML Profile,请读者参阅RSA相关的帮助文档。本例所用profile的id为GetSetProfile,包含一个名为GetterAndSetter的stereotype,扩展自Property:


图7 GetSetProfile
图7 GetSetProfile

5.3 实现扩展规则

DefineGetterSetterRule的实现:


public boolean canAccept(ITransformContext context) {
  // 本规则接受的源模型对象为应用了GetterAndSetter Stereotype的Property
if (context.getSource() instanceof Property){
	  Property attribute = (Property)context.getSource();
	  if(attribute.getAppliedStereotype(GETTER_SETTER_STEREOTYPE) != null){
	    return true;
	  }
}
return false;
}
protected Object createTarget(ITransformContext context) {
  /**
   * 记录需要处理的property的信息,并存放在转换上下文中,供CreateGetterSetterRule 使用
   */
Object[] propertyInfo = new Object[2]; 
propertyInfo[0] = context.getSource();
propertyInfo[1] = context.getTarget();
List properties = (List)context.getPropertyValue("createGetAndSet");
if (properties == null){
ITransformContext classContext = context.getParentContext();
List list = new ArrayList();
	list.add(propertyInfo);
	classContext.setPropertyValue("createGetAndSet",list);
}else{
properties.add(propertyInfo);
}
return propertyInfo[1];
}

CreateGetterSetterRule的实现请参考本文附带的代码。

5.4 扩展UML2JAVA转换

为了扩展模型转换,需要从com.ibm.xtools.transform.core.transformationExtensions扩展点进行扩展,将之前实现的转换规则添加到需要被扩展的模型转换中。本文以DefineGetterSetterRule为例,介绍如何添加扩展规则:


<TransformationExtension
version="1.0.0"
  name="DefineGetterAndSetter"
  enabled="true"
targetTransformation="com.ibm.xtools.transform.uml2.java.internal.UML2JavaTransform" 
id="com.ibm.xtools.transform.samples.uml2java.getterSetter.extension.defineOperation">
<RuleDefinition
name="DefineGetterAndSetterOperation"
class="com.ibm.xtools.transform.samples.uml2java.getterSetter.DefineGetterSetterRule"
id="com.ibm.xtools.transform.samples.uml2java.getterSetter.DefineGetterSetterRule">
</RuleDefinition>
<ExtendTransform
   targetTransform="com.ibm.xtools.transform.uml2.java.internal.PropertyTransform">
   <AddRule
id="com.ibm.xtools.transform.samples.uml2java.getterSetter.DefineGetterSetterRule">
   </AddRule>
</ExtendTransform>
</TransformationExtension>

targetTransformation属性指定了被扩展的模型转换,RuleDefinition定义了扩展规则,ExtendTransform则将扩展规则添加到具体的转换中。

5.5 运行测试

至此,对UML2JAVA转换的扩展实现已经完成,从RSA再启动一个RSA Workbench实例,加载扩展转换插件。创建一个UML模型,在模型中创建Account类:


图8 Account类
图8 Account类

Account类包含四个属性,其中password和balance属性应用了GetterAndSetter Stereotype,在转换之后会生成对应的Get和Set方法,id属性也应用了GetterAndSetter Stereotype,但id为只读属性,因此在转换之后只会生成对应的Get方法。userName没有应用这个Stereotype,则不会生成Get和Set方法。以Account类为源模型,执行UML2JAVA转换,生成Java程序:



由生成的代码可以看出,在转换框架执行UML2JAVA转换的时候,会将两条扩展规则加载执行。





回页首


6 总结

模型转换在模型驱动的开发过程中起着重要的作用。RSA提供了一个功能强大、易于扩展的模型转换框架。该框架是一个基于规则的执行引擎,模型转换的开发者只需将转换定义为一系列转换规则即可,模型转换框架会负责加载执行规则,并提供统一的模型转换配置管理,在很大程度上简化模型转换的开发过程。



参考资料



关于作者

IBM中国软件开发实验室SOA设计中心 是IBM全球四个SOA设计中心中最大的一个,成立一年多来,已经取得了可喜的成果。我们在全球范围内实施了多个 SOA 应用项目,为多个行业的客户提供了 SOA 解决方案。我们正在实施的 SOA 项目涵盖了很多的重要行业,包括零售业、航运业、电力、银行、保险等等。通过这些不断增长的成功案例,我们不仅深入地推广了 SOA 的理念,树立了 SOA 成功实施的范例,也为我们的队伍积累了经验,培养了人才。与此同时,我们还是 IBM 开发 SOA 的软件平台 -- SOA Integration Framework -- 的主力军。该产品基于模型驱动的思想,旨在最大化地重用软件资产,它为 SOA 项目的实施提供了一整套源自成功实践的方法论,设计范式和工具集。它的出现将极大地方便 SOA 系统架构师、设计人员、开发人员快速地开发 SOA 应用项目。
参与本系列撰写的主要技术人员包括:
毛新生 IBM 中国软件开发实验室 资深经理, SOA计中心中国区 首席架构师
何蕾 IBM 中国软件开发实验室 SOA设计中心 高级软件工程师
孙瑛霖 IBM 中国软件开发实验室 SOA设计中心 软件工程师
田晨 IBM 中国软件开发实验室 SOA设计中心 软件工程师
王强 IBM 中国软件开发实验室 SOA设计中心 软件工程师




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款