内容


通过使用 IBM Rational Software Architect 7.0 扩展从 UML 到 C++ 的转换

如何一步一步地扩展该转换

Comments

扩展转换的一般原因

扩展转换您可能有很多种理由。例如,您想要向方法添加自动生成的文件,该方法列出了参数以及返回种类。或者您想要改变转换产生的默认方法主体。不管是哪种情况,扩展转换都能帮助您去产生自己的,自定义的资源。

过程与 V6 有什么不同

UML 到 C++ 的转换在 V7.0 中得到完全的重新设计。以前在 V6 中,转换在完成一个 UML 模型后,直接将其写进输出缓冲器中,该缓冲器最终将删去这些作为 C++ 文件的内容 。因此您需要决定,在缓冲器中写进什么内容。

在 V7.0 中,转换在完成一个 UML 模型后,将构建一个 C++ 抽象语法树状图,它只不过是一个 EMF 模型 。然后转换使用 JET2 来将模型转换成 C++ 资源。 您需要利用该树状图,来以任何方式编辑生成的代码。因此在这种情况下,您需要有一些该中级模型的知识,特别是一些关于参加了 C++ 代码生成的核心部分的知识,例如,这些部分有类,结构联合,枚举,方法以及属性 。

模型类隶属于一种叫做 com.ibm.xtools.cpp.model 的插件。模型的 Javadoc™工具是作为文件的一个附属物,如图 1 中的图表所示。

图 1. UML 到 C++ 的转换
2 个图表以及代码
2 个图表以及代码

本篇文章包含的范例

在分开的文件(参见下载部分)中,本篇文章所举的范例,教您打下了扩展 Rational Software Architect v7 中 C++ 转换的基础。如果您已安装了该软件,您只需在您的插件目录中提取出范例,重新启动 Rational Software Architect,并运行以下转换:

  • 范例 1 将默认的方法主体,改变成了您所想要的。
  • 范例 2 在每个方法之前添加了一个注释。
  • 范例 3 在每个属性之前添加了一个注释。

本篇文章只带您学习范例 1 的应用。范例 2 与范例 3 相似,您可以自己去探索它们。

使用扩展要点概述

UML 到 C++ 转换可通过 com.ibm.xtools.transform.core.transformationExtensions 扩展点得以扩展。该扩展点让您能够添加规则,内容提取器,或者向一个已存在转换的转换 ,例如 UML 到 C++ 的转换。对于一个转换而言,以下项目可被定义:

  • Property:转换的新属性
  • RuleDefinition:扩展当前行为的新规则
  • ExtractorDefinition:制作模型的新内容提取器
  • TransformDefinition:新转换(内含提取器以及规则)
  • ExtendTransform:向一个已存在转换添加新规则,提取器或者转换

通过添加新规则,本篇文章致力于扩展从 UML 到 C++ 的转换,因为大多数情况下,这一般是您最需要做的。

如何向 C++ 转换添加新规则

为了向转换添加一个新规则,您需要完成三件事:

  1. 通过使用 RuleDefinition 来定义规则。
  2. 通过使用 ExtendTransform 来扩展转换以插入新规则。
  3. 定义代表规则的类。

图 2 是在生成的代码中,添加一条规则,以改变默认的方法主体后,您的 XML 插件外观的快照。特别注意该行:

com.ibm.xtools.transform.uml2.cpp.bodyextension.CPPMethodBodyRule (AddRule)
图 2. 在添加一条规则后的 XML 插件
XML 代码屏幕截图
XML 代码屏幕截图

1. 定义新规则

列表 1 向您显示了 RuleDefinition 是什么样的。

列表 1. RuleDefinition 范例
<RuleDefinition
       class="com.ibm.xtools.transform.uml2.cpp.bodyextension.CPPMethodBodyRule"
       description="Adds a user defined body to a method" 
       id="com.ibm.xtools.transform.uml2.cpp.bodyextension.CPPMethodBodyRule"
       name="C++ Method Body Rule"/>

正如您所猜到的一样,class name 参考了定义规则的实际类。属性 ID 单独识别了转换框架的规则。属性 name description 只是:您所选择规则的名字,以及它的功能的描述。

2. 插入新规则

在您定义新规则以后,您需要在合适的转换中合适的位置上插入该转换 ,通过使用如列表 2 所示的 ExtendTransform .方法,您可以做到这点。当然,appropriate transform 部分很容易理解。但是 appropriate place 需要一些注释,这样我们就能很快理解它了。

列表 2. ExtendTransform 范例
       <ExtendTransform targetTransform=
       "com.ibm.xtools.transform.uml2.cpp.ClassOperationTransform">
       <AddRule 
       id="com.ibm.xtools.transform.uml2.cpp.bodyextension.CPPMethodBodyRule"
       index="1">
       </AddRule>
</ExtendTransform>

在该范例中,方法主体规则需要进入一个 Operation 转换。我们已经选择了 ClassOperationTransform,这意味着,该新规则只能影响在 UML 类或者固定的 UML 类中,定义的操作的行为,例如,在 UML 界面上定义的操作。注意,该规则的 ID ,与您在使用 RuleDefinition 来定义新规则时使用的 ID 相对应。

另一个需要注意的重要事项是 index,它决定了在您插入的转换链中,您的规则将链接到哪里。这非常重要,因为这决定了,对已转换的元素进行了什么类型的处理(在本例中,是一次 UML 操作)。它还能够影响继承规则的处理,因为通过改变转换的目标,您的规则可能影响到转换的行为,这一点您将在下一段落中看到。

在这种情况下,您插入的规则,是作为 ClassOperationTransform 中的第二规则(indexing 开始于 0)。 在下载文件中, 我们已经给出了每一个转换,以及规则链接情况的概述。在这里就可以说明,该规则什么时候起效,在上面提到过的抽象语法树状结构中,已经创建了一个目标 C++ 操作。这将传递给您的规则,并作为您的转换目标,而且这是您需要掌控的数据结构,以得到您想要的操作。

3. 定义规则类

定义一个新规则的最后一步,是定义一个代表该规则的类。在这种情况下,它代表了 CPPMethodBodyRule 类。

列表 3 是一个显示如何执行规则类的代码片段。

列表 3. 执行规则类的范例
package com.ibm.xtools.transform.uml2.cpp.bodyextension;

import com.ibm.xtools.cpp.model.CPPOwnedMethod;
import com.ibm.xtools.transform.core.AbstractRule;
import com.ibm.xtools.transform.core.ITransformContext;

public class CPPMethodBodyRule extends AbstractRule {
	
	public boolean canAccept(ITransformContext context) {
		Object object = context.getTarget();
		if (! (object instanceof CPPOwnedMethod))
		{
			//this can happen if the method was not processed. 
//Then the target container would contain 
//the parent of the method.
			return false;
		}
		return true;
	}

	protected Object createTarget(ITransformContext context) 
throws Exception {
		System.out.println("Invoking extension");
		
		String newBody = new String ("//User defined body");
		Object object = context.getTarget();
		CPPOwnedMethod method = (CPPOwnedMethod)object;
		method.setMethodBody(newBody);
		
		return method;
	}

}

所有的规则类必须扩展转换框架定义的 AbstractRule 类。它同样应该超越 canAccept createTarget 方法。

方法 canAccept 基本上决定了,该规则是否能够接受传递给它的转换内容。转换内容正如它声称的那样:它含有哪个元素被转换(即 ITransformContext.SOURCE 对象),它将被转换成什么(即 ITransformContext.TARGET 对象),以及转换准备将转换对象置于何处(即 ITransformContext.TARGET_CONTAINER 对象)等相关信息的内容。

在本例中,正如您在前面章节中看到的那样,规则被插入 ClassOperationTransform,而且它的转换源是一次 UML 操作。但是,规则不应该为该转换不准备处理的操作而运行。例如,如果您在一个模板例子,或匿名联合体中错误地为操作建模,那么这样的操作应该被弃除。在这里,方法 canAccept 检查 CPPOwnedMethod 种类的目标对象是否为操作创建了,这意味着该操作能够被安全地处理。(稍后更多关于 CPPOwnedMethod ,那时我们将讨论 C++ 模型)。

第二个方法是 createTarget 方法,在这里您要更改产生的目标,这就是您要着手进行的。这里,例如,方法主体被设置成您所选择的字符串。注意,在 canAccept 方法中,您已经检查以确定,只当目标是 CPPOwnedMethod 时该规则才被激活。因此,在转换期间访问 canAccept 后的 createTarget 方法中,您可以放心地假设,目标确实是 CPPOwnedMethod

提示:
确保您从 createTarget 方法中返回了修改后的 CPPOwnedMethod

如果想查看另外两个例子,并得到更多有用信息,您可以下载与本篇文章相配套的 PDF 文件。


下载资源


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Rational
ArticleID=349433
ArticleTitle=通过使用 IBM Rational Software Architect 7.0 扩展从 UML 到 C++ 的转换
publish-date=10312008