本文介绍了使用IBM Rational Software Architect进行UML建模元素的扩展与定制的基本实现方法。通过对一个实例场景的引用,文章重点阐明如何在RSA中基于Eclipse插件技术完成对RSA中UML建模元素的容器,即Palette的静态、动态扩展,以及对Palette扩展工具项定制时需要注意的技术难点。
RSA为基于UML进行业务建模并完成底层代码生成的开发人员提供了可视化的建模环境,开发人员可以因此方便的从Palette中拖取合适的UML元素来表达业务语义。但是在很多时候,开发人员希望在Palette中定制自己的工具项,从而便捷的使用具有更丰富业务概念和关系语义的UML元素。本文基于RSA
6.0中UML建模元素的容器--标准palette插件,从静态配置和动态加载两种途径提供了扩展Palette的基本方法和其中需要关注的技术难点。文章也举例说明了如何在具体实现中嵌入对Palette扩展工具项所生成的UML元素的定制。
IBM® Rational Software Architect -- IBM软件开发平台的一部分,是IBM在2003年2月并购Rational以来首次发布的Rational产品。RSA作为一个集成化的设计和开发工具,支持使用UML进行模型驱动的开发以得到架构良好的应用和服务。RSA是在Eclipse
3.0 的基础之上创建的,因而支持Eclipse 提供的使用特性,其中最为主要的就是Eclipse插件技术。
本文所要讨论的Palette就是使用Eclipse插件技术嵌入到RSA工具环境中的一个UI组件。假设有如下的场景:
开发人员使用RSA为一个网上电子零售业务进行业务建模,在建模过程中需要大量重用如下4个业务角色:
使用RSA建模环境下原有的Palette,需要反复拖入Class元素并为每个这样创建的Class赋予相应的构造型(Stereotype)以表达如上之一的业务角色。如下是使用RSA中未扩展的UML建模环境进行建模时的界面:
图1 使用RSA经典UML建模环境进行网上电子零售业务建模
为了提高建模的效率,开发人员希望在Palette中定制代表了这些业务角色的新元素。本文基于上面的实例总结了开发人员在进行Palette扩展时所采用的基本实现技术和难点。
从前面的讨论可以知道,RSA是构建在Eclipse3.0的基础之上的。Eclipse的插件结构是Eclipse重要的基础设施和体系结构,其中应用扩展点是两个或者多个插件完成协作的基础。基于RSA的Palette静态扩展方法就是通过Eclipse,定义单独的插件来完成Palette扩展点的定义,从而增加新的建模功能。
本节将通过一个简单的"零售业务建模"的例子向您逐步展示如何来对RSA的Palette进行扩展。在"零售业务建模"中,我们需要四类角色:零售提供商、商品、消费者和零售商。为了提供更好的操作感觉和交互过程,我们将扩展Palette面板,这样进行零售业务建模就如同UML建模一样的直观快捷。
同RSA平台中其他插件一样,Palette也是通过扩展点来进行定义的,所以,必须要在插件清单plugin.xml文件中声明所需要的扩展点,并且提供相应的实现类。对于Palette而言,要声明的扩展点就是com.ibm.xtools.presentation.paletteProvider,要提供的实现类必须实现com.ibm.xtools.presentation.internal.services.palette.IPaletteProvider接口。当然,也可以使用缺省的com.ibm.xtools.presentation.internal.services.palette.DefaultPaletteProvider类,因为DefaultPaletteProvider已经完全实现了IPaletteProvider接口,在RSA的一些建模插件中,可以查找到使用的都是这个缺省的Palette提供类。
就palette而言,只有这样的声明是不够的,更加完整的扩展声明如清单1所示。
清单1 一个完整的Palette扩展声明
其中,比较重要的部分就是contribution节点,该节点声明了要为Palette添加内容,他的属性factoryClass必须要指定一个实现类,提供生成相应工具的工厂方法。在Contribution节点中,通过声明entry节点来实现在Palette面板上要添加的抽屉(drawer,Palette面板上容纳工具的容器)或者工具盒(tool)。例如,首先要添加一个容纳零售业务建模工具的抽屉,那么清单2中的片断就完成了这样的声明:
清单2 一个典型的Palette抽屉扩展声明
以清单2为例,上述entry节点中
- label声明了要在Palette面板中显示的名字;
- kind声明了该Entry是drawer类型(或者是tool类型);
- id声明了他的唯一性并在程序中将使用该id来唯一标识;
- path声明了他在Palette或者drawer中的位置,他的格式同Menu和Toolbar中扩展的path格式是一致的。
类似的,在添加了抽屉之后,就要在抽屉中添加建模的工具,对应的就是零售提供商工具、商品工具和消费者工具,如清单1中所示。
这个时候我们新建立一个插件工程,并把上述Palette扩展声明填写进插件清单文件中去,然后以工作台方式运行,我们新建的这个插件也会被自动装载进启动的工作台中。新建"UML模型",打开"建模"视图,我们可以在palette面板上看到如图2的所示的截图。
图2 用于零售业务建模的Palette片断
虽然,我们新扩展的零售建模工具已经在Palette面板中出现,但是他们不能执行任何操作,甚至会抛出异常,因此,我们要进一步添加功能方面的扩展。
首先,对应着Palette中的工具,在插件中要有相应的工具类来完成该工具的操作。这个工具类通常要求继承自com.ibm.xtools.presentation.internal.tools.CreationTool,例如实现消费者的模型生成工具类的代码段如下:
其中,
- 构造函数,传进参数IElementType,定义该模型具有的语义信息;
- performCreation,具体的执行动作,为了简单起见,我们都是调用了父类的方法。
类似的,我们也实现了零售提供商和商品的生成工具类,即SupplierCreationTool和ProductCreationTool。这些工具生成类的对象控制都是由插件清单中指定的工厂类来进行控制的,如清单1中的片断,
这个工厂需要继承自com.ibm.xtools.gef.internal.ui.palette.PaletteFactory.Adapter,事实上PaletteFactory的Adapter已经完成了绝大部分的工作,在例子中实现的工厂类BizdemoPaletteFactory中仅仅需要重载一个方法就可以了,如下面程序段所示:
其中:
- 参数toolId,表示的是目前需要生成的工具id,对应的也就是插件清单文件中Entry节点声明的id;
- 返回值,返回对应的生成工具对象,也就是我们前面已经实现的四个生成工具类;
- 传递给生成工具对象的ElementType,为了简单起见,我们将UML中的CLASS类型传给了生成工具,在第五章中,我们将介绍如何对他进行进一步的扩展,包括在语义方面的扩展。
至此,我们就已经用静态扩展的方式对Palette进行了扩展,提供了一个简单的零售业务的建模工具。
上节给出了通过编辑RSA插件工程的plugin.xml文件中提供的扩展点进行静态Palette扩展的基本方法。在一些特定情况下,开发人员在进行业务建模和业务开发时无法完全穷举业务模型中所需要的所有角色,并在plugin.xml的扩展点中完成定义。就网上电子零售业务而言,未来该业务的供货来源很有可能被扩展到海外,并且需要为该角色添加"国籍"、"报关单"、"报关"等新的属性和行为。为此需要从提供商中分离出"国外提供商"这样新的业务角色。"国外提供商"和原有的"国内提供商"属于相同的Palette分组,但是重新编码、编译、构建原有的插件工程会给代码维护带来一定的困难,因为开发人员无法预料在将来是否还有添加更多的角色。
综上,开发人员希望在提供静态Palette扩展的插件(下文称之为BizDemo核心插件)内提供必要的扩展点,允许未来新的业务角色以新的插件的形式嵌入到RSA环境中来。这样的插件下文称之为BizDemo扩展插件)将使用Palette核心扩展插件暴露的扩展点,以允许核心插件在动态加载时读取其工具项配置,将扩充的工具项添加到Palette中来。
进行Palette动态扩展的第一步是为第3节中创建的BizDemo核心插件开放一个扩展点,体现在插件工程中,就是在plugin.xml中添加如下清单所示的声明:
清单3 为支持Palette动态扩展在插件工程中添加的扩展点
该声明规定扩展点的id为bizdemoProviders,该id将作为未来提供扩展业务角色语义的新插件的定位扩展点的依据。同时,上面的声明还指出,未来这样的新插件必须在自己的plugin.xml声明中使用核心插件schema目录下bizdemoProviders.exsd文件所规定的XML语法来表达对该扩展点的扩展声明。因而,BizDemo核心插件必须在自己的工程目录下创建一个schema目录和其下的一个名为bizdemoProviders.exsd的XSD文件。如下给出了该文件的关键片断:
清单4 描述BizDemo核心插件bizdemoProvider扩展点的XSD片断
下面的步骤就是创建一个用来描述"国外提供商"业务语义的基于BizDemo核心插件的扩展插件。首先,使用RSA创建一个普通的插件工程,并在plugin.xml中添加如下的声明:
清单5 为使用在BizDemo核心插件中定义的扩展点而在扩展插件plugin.xml中给出的声明
该声明片断完全符合清单4定义的语法,它表示新的插件将使用BizDemo核心插件的扩展点bizdemo.palette.bizdemoProviders(bizdemo.palette是BizDemo核心插件的id,也作为扩展点的名字空间),并在bizdemoProvider元素的属性descriptor中指出了提供新的业务角色语义的文件名。
接下来在新插件工程的根目录下生成名为bizdemo-role.xml的XML文件,并在文件中如下描述"国外提供商"Palette扩展工具项的基本属性:
清单6 描述了"国外提供商"Palette扩展工具项属性bizdemo-role.xml声明片断
该声明规定了将要添加到BizDemo抽屉中的"国外提供商"工具项的id、label、large_icon、small_icon、description等属性。这些属性和第3节清单1中所列举的静态定义属性一一对应。
最后,我们需要再次修改BizDemo核心插件的代码和部分声明,使之支持对所有扩展了该插件的BizDemo扩展插件的角色信息动态提取:
- 创建一个DynaRoleInfo 类,并定义和清单6所列项对应的属性,用来动态保存从每个角色扩展插件中读出的信息;
- 创建一个RoleManager类管理所有DynaRoleInfo的实例。该类提供静态属性Map roleList和相关的get-set方法完成运行时对DynaRoleInfo的实例的加入和查询。具体实现时,可以使用每个动态角色信息中的id作为Map的key,而将相应的DynaRoleInfo实例作为Map的object;
- 创建一个RoleProviderInfo类用来解析每个BizDemo扩展插件中的bizdemo-role.xml文件,并将信息加载到一个DynaRoleInfo实例中。RoleProviderInfo类的代码逻辑可以只实现对一个bizdemo-role.xml文件的解析,而将所有对扩展了核心Palette插件的插件集合的迭代放到RoleManager中完成。例如,RoleManager提供initialize方法来完成该逻辑:
RoleProviderInfo的构造函数将定位参数提供的扩展点入口所属的插件,并由此找到相应的bizdemo-role.xml,完成解析:
最后,我们需要做两个代码段的修改。首先如第3节所述的那样,添加一个继承了com.ibm.xtools.presentation.internal.tools.CreationTool的DynaCreationTool,并在BizdemoPaletteFactory的createTool方法中添加一个if分支:
……
new DynaCreationTool (UMLType.CLASS);
|
其次,修改清单1中对Palette扩展的实现类声明,将paletteProvider的属性class改为自定义的类bizdemo.palette.
DynaProvider,并扩展其contributeToPalette方法如下:
动态添加一个工具项的典型代码片断如下:
经过如上步骤,使用RSA的Runtime Workbench动态加载这两个插件,用户将能够看到在Palette中动态创建的"国外提供商"工具项:
图3 创建了"国外提供商"工具项的零售业务建模Palette片断
在一般情况下,通过扩展Palette得到的工具项都要对其生产的UML元素进行定制,以表达在开发人员看来更丰富的业务含义。这样的定制可能包括:
- 为创建的UML元素赋予新的构造型;
- 为创建的UML元素添加新的构成元素,如在Class上添加预定制的属性和操作;
- 为创建的UML元素定制特定的外观,如设置其背景色、图标、字体等。
限于篇幅,我们将只介绍定制第4节创建的"国外提供商"工具项生成的UML元素的背景和构造型的实现方法。
首先,需要在第4节创建的"国外提供商" BizDemo扩展插件的bizdemo-role.xml中补充声明相关的定制信息:
该定制信息说明,由"国外提供商"Palette工具项生成的UML元素将被应用InterProviderProfile这一Profile定义的InterProvider构造型;并且,该UML元素的背景色将设为由十六进制整数EADDAA对应的RGB值标志的颜色。
其次,我们需要修改BizDemo核心插件中DynaRoleInfo类的属性,使之包含所有定制的属性的集合。应该说,BizDemo核心插件规定了定制属性的集合及其在bizdemo-role.xml的描述语法(类似清单4的bizdemoProviders.exsd),并依据它完成DynaRoleInfo类的定义。而每个BizDemo扩展插件的bizdemo-role.xml只是选择表达自身语义的一部分属性进行描述。类似的,我们需要在RoleProviderInfo类中修改相关的XML解析逻辑,以加入对定制信息的解释支持。
最为关键的是下一步。由于RSA认为UML模型和UML图属于不同的分类体系(而实际上确实如此,UML模型表达了模型自身的属性和关系,UML图则给出了模型的一个图形化的显示方案),一个具体的UML元素通过Palette被生成到UML图的过程中,两者在不同时刻生成。如构造型这样属于UML模型的元素在UML元素被绘制到UML图之前就被加入到工具项的结果对象中。而如背景色这样属于UML图的元素则在真正在图上绘制生成的结果对象时才被加载。
反映到我们的解决方法上,对于构造型,我们必须修改BizdemoPaletteFactory使得创建的UML元素不简单是个Class。办法是
- 创建如下的一个特殊的Classifier DYNACLASSROLE,并在BizdemoPaletteFactory的DynaCreationTool方法中要求对于"国外提供商"创建的结果对象是这个DYNACLASSROLE:
- 在BizDemo核心插件的plugin.xml中加入如下的声明
该声明对com.ibm.xtools.presentation.semanticProviders扩展点进行了扩展,在用于扩展的类bizdemo.palette.DynaSemanticProvider的getCreateComponentElementCommand方法中,要求用CreateBizDemoCommand类(继承了com.ibm.xtools.uml.core.internal.commands.CreateClassifierCommand)的构造函数返回结果对象:
- 最后,在CreateBizDemoCommand类的doExecute方法中在返回缺省创建的UML结果对象前应用该构造型:
背景色的定制要简单一些,实现它的关键在于捕获在RSA的UML图编辑器中创建UML对象这一事件:
- 在Palette的核心插件plugin.xml中添加如下声明:
该声明用自定义的类bizdemo.palette.actions.BizdemoCustomizationAction对org.eclipse.ui.actionSets扩展点进行了扩展。
- 类bizdemo.palette.actions.BizdemoCustomizationAction继承了org.eclipse.ui.IworkbenchWindowActionDelegate,能捕获Eclipse中多类UI操作产生的事件,这里我们只选用selectionChanged,因为当一个新的UML元素在UML图中生成时,总是选中新创建的元素,因而触发该事件:
这里尤其要注意的是,由于设置背景色输入更新操作,所以在如上代码片断第3行创建的资源操作类一定是ResourceSetModifyOperation,而不能是ResourceSetReadOperation,否则将因为资源处于只读状态而抛出异常。
采用本节所述的定制方式,对网上电子零售业务中的所有角色进行定制后的模型界面如下图所示:
图4 使用BizDemo扩展Palette工具项进行网上电子零售业务建模
从本文的介绍可以看出,由于RSA是基于Eclipse技术搭建起来的,架构师或者开发人员在使用RSA提供的环境进行业务建模时,如果需要对相关的UI组件进行扩展,一般都可以考虑应用RSA内部实现该组件的插件的扩展点,编写新的插件,并在plugin.xml中的扩展点对应的标签内遵循XML模式定义进行扩展描述。如果确实需要在运行时动态加载相关扩展,则可以进一步在新的插件中暴露扩展点,并为未来扩展该插件的插件工程约定扩展项的描述规范。
需要特别指出的是,本文对Palette扩展的技术实现是基于RSA 6.0.0.1版本中标准Palette实现的API。如果RSA在未来被升级,这些API可能会有所变化,从而造成文中所涉及的相关代码和配置将不再准确。但是开发人员仍然可以复用本文的实现思想进行相关调整,从而保证应用开发的正常进行。
1. RSA帮助文档
2. RSA:
http://www.ibm.com/developerworks/rational/products/rsa/
3. UML:
http://www.omg.org/technology/uml/index.htm
4. The developerWorks Rational zone:
http://www.ibm.com/developerworks/cn/rational/
描述 |
名字 |
大小 |
下载方法 |
Sample code |
PaletteDemo.rar |
63 KB |
|
|