IBM® Rational® Software Architect 包含了一系列的预定义转换。其中的一些用于将一个 UML 模型转化为源代码。UML 到 C# 转换,如同其他一些模型到代码转换一样,可以被扩展。本篇文章列出了创建一个简单的扩展示例所需的步骤,该扩展示例演示了此功能的核心能力。
对于 Rational Software Architect 的大多数特性,您要使用标准 Eclipse 扩展机理,创建一个插件和执行特定扩展点来扩展它。本篇文章并没涉及到一般的插件开发,如果您需要这方面的更多信息,您可以查看本文的 参考资源 部分。但是,本文包括了创建以及测试一个转换扩展,所需要的一些插件开发技巧,并将重点放在自定义 C# 转换上 。
下面列出的,是您想要扩展转换可能的几个原因,您可能想要:
- 向您的方法添加自动记录,记录什么列出参数以及返回类型。
- 向每一个产生的类型添加作者信息。
- 更改转换产生的默认方法主体。
在每一种情况下,扩展转换都能帮助您,生成您自定义的资源。
如图 1 所示,当一次 UML 到 C# 转换启动时,它从配置作为转换资源的 UML 模型开始。
图 1. 总体转换结构
该转换处理整个模型,如图 2 所示。转换浏览了资源,并组成了一个 C# Abstract Syntax Tree(AST),而这又是另外一个 Eclipse 建模框架(EMF)模型。然后转换使用 Java Emitter Template 2 (JET2),来将 AST 转换成 C# 资源 。在本文的结尾,您可以找到目标的一个完整列表。
图 2:配置转换扩展元素
对于这个简单的示例,您将定义一个简单的,类层次的扩展,每当一次转换转换将一个 UML Class 元素转化成 C# 源文件时,都会激活该扩展。本扩展仅仅搜寻为该类定义的关键字,然后使用它们,来添加与源代码中的类相关的新记录标签。
您需要执行的总体步骤包括:
- 为您的转换扩展创建一个新的插件项目。该项目可以与其他的扩展联合起来。但是,为了让这个例子变得简单,您需要从头开始创建一个新的项目。
- 添加一系列需要的插件附件。这些插件定义了您正在运行的扩展点,并提供了激活扩展您将需要的 APIs。
- 在插件描述器中,定义能识别您将要扩展的转换的扩展点,以及您想要做出更改的其中的点。如果您想要得到关于一个扩展点定义(以及怎样去构建它)的更多具体信息,参见 参考资源 部分中的 有关 Eclipse Plug-in Architecture 的说明(Notes on the Eclipse Plug-in Architecture)部分。
- 提供一个 Keyword Documentation Rule 的 Java 工具,每当转换遇到您注册的元素类型时,都会使用到该工具。
- 通过启动一个运行时工作台,并执行一次 UML 到 C# 转换,来测试转换。
您的转换扩展从一个新的插件项目开始。
- 选择 File > New > Project。
- 从项目类型列表中选择 Plug-in Project,然后点击 Next。
- 在 New Plug-in Project 向导的第一个页面中,输入一个有效的项目名。插件的 Eclipse 惯例,是使用一个如图 3 所示的 URI 域。
图 3. New Plug-in Project 向导
- 在第二个界面中(图 4),您应该更改默认的 Plug-in Name 区域。输入 Sample UML to CS Extension.。其他默认的设置可以接受。
图 4. New Plug-in Project 向导属性页面在最后的页面中,不需要选择一个插件模板,因为那里没有为转换扩展准备的模板,只有新完成的转换。
- 清除模板选项并点击 Finish,如图 5 所示。
图 5. New Plug-in Project 向导最后的页面当向导设置完成后,一个新创建的插件项目会生成,并且项目描述器的 Overview 页面会打开,如图 6 所示。
图 6. 新项目结构接下来的一步,是添加作为附件的一些插件(在切换至 Plug-in Development 视角以后)。这些插件包含了扩展点定义,您将为该点定义提供一个工具,以及在扩展工具中将会用到的 APIs。
- 切换至附件标签(在编辑器的底部可以找到它),并添加作为附件的如下插件。
- com.ibm.xtools.modeler
- com.ibm.xtools.transform.core
- com.ibm.xtools.transform.uml2.cs
- com.ibm.xtools.cli.model
结果得到的列表应该与图 7 相似。
图 7. 独立的插件
接下来要讲的一步,是您将要向一个或多个扩展点提供的工具。
- 切换至 Extensions 标签。
- 点击 Add 按钮以添加一个新扩展。对话框如图 8 所示。
- 输入扩展点 com.ibm.xtools.transform.core.transformationExtensions。
- 当找到它时,选中它并点击 Finish 按钮。
图 8. 新扩展对话框您需要在扩展点定义中提供更多的信息。您可以在 Extension 标签页面的用户界面中,输入这些值。但是大多数人发现,只编辑 plugin.xml 文件的纯 XML 会更加容易
当首次定义一个扩展时,会创建该文件(在那之前,并不需要创建文件,所以 New Project 向导并没有创建它)。切换至 plugin.xml 标签,您将会看到 XML 资源,您可以编辑它。
对于本例,向扩展点添加如列表 1 所示的具体内容。
列表 1. 扩展申明
扩展元素的主体,在 Rational Software Architect Core Transformation 组件这种情况下(com.ibm.xtools.transform.core.transform),是由扩展点提供者定义的。该扩展预计了 TransformationExtension 子元素(为每一个扩展转换的类型)。这些元素中的每一个,都定义了扩展哪一个转换。
- 对于这个简单的例子,用 IDcom.ibm.xtools.transform.uml2.cs.internal.UML2CSTransform. 来指定 targetTransformation。
- 您应该为 ID,版本号,名字,以及可用 Boolean 值应用合适的值。
每一个转换扩展,将子元素定义为一个规则定义,它指定了执行规则界面的类。该类完成了构建转换的大多数工作,提供了放置您自定义的过程逻辑的地方。它作为一个单独的元素定义,因为对于一个单独的类来说,构建转换的大多数部分(也就是类,属性,以及操作)是可能的。
一旦定义了所有的规则,它们将与 ExtendTransform. 元素一起构建的转换的一部分协调起来。该元素定义了规则要构建转换的一部分。换句话来说,一旦规则被创建,我们需要指定什么时候去使用它们 。
对于这个简单的例子,每当一个新类被转换时,您都要构建转换 。targetTransform. 的值应该是 com.ibm.xtools.transform.uml2.cs.internal.ClassTransform。目标转换 ID 的完整列表,可以在本文结尾的 附录 段落中找到。
因为不止一个规则可以构建转换的任意一个特殊部分,所以把它们集中到这里,作为 ExtendTransform. 元素的子元素。可能您在您的项目中只有一个定义的规则,所以这里有一个清晰而简单的映射 。在各种插件的条件下(或者 transformationExtensions,TransformExtension,RuleDefinition,ExtendTransform,或者 AddRule 元素的多种实例), 制作一个与图 2相似的图表,将是有帮助的。元素 RuleDefinition 的 id 必须与元素 AddRule 的 id 相匹配。
当您完成您的编辑之后,保存文件。您应该注意到,在文件 plugin.xml 靠近线的左部边缘区域,有一个很小的错误图标,该文件指定了执行类。这意味着在项目中不能找到该类。您可以启动 New Class 向导,并使用它来创建类文件。您也可以使用 File > New 菜单手动创建该类。
- 不管您以何种方式在 Eclipse 中创建 Java 类,在预定的包裹中创建一个,并给它起一个合适的名字。
您将要扩展 Rational Software Architect 转换框架类com.ibm.xtools.transform.core.AbstractRule。因为该类是一个超类,所以只有三个应该被忽略的方法。
- canAccept:其作用像一个过滤器,决定该规则是否可以接受资源元素
- createTarget:用于从资源元素中创建目标元素
- isSourceConsumed:允许或阻止在该资源元素上的进一步规则执行
其中每一个方法接受一个 transformation context object,您可以对它进行查询,以获取对资源以及目标对象的访问权。一个转换内容对象,是与转换相关的各种属性的集合体,该集合体包括了总体转换配置属性(从 Preferences 中),以及当前执行转换的属性 。
利用这些信息,您可以决定是否处理特定的类(canAccept),或者对于该类的进一步处理是否终止 (isSourceConsumed)。如果该扩展接受了内容,那么方法createTarget()用于对转换做出实际构建。换句话讲,您使用 canAccept() 方法,来进一步决定什么时候执行您的规则。您的扩展的逻辑,将出现在 createTargetMethod() 中。您也可以决定,是否继续处理与规则相关的元素。
对于这个简单的转换扩展,在 isSourceConsumed 方法中返回 false,以指示进一步的处理应该继续(如列表 2 所示)。这同时还可以看出,扩展并不意味着,这些特殊元素的所有转换工作都已完成 。
继续处理本例,在 canAccept() 方法中指示,当资源元素是 UML Class 类型,并且那里至少有一个定义的关键字时,您可以接受一个特殊类,如果那里没有任何关键字,那么您就不需要再做什么,这样表示您并不感兴趣。通过作为一个论题传递的转换内容,访问资源 UML 类。
内容中的 getSource() 方法向一个 UML 类返回一个引用,因为您在扩展点中指定,您只对 Class 转换感兴趣。向一个 UML 类输入资源对象,然后从该对象中获得关键字列表。如果列表为空,则返回 false。如果列表中含有关键字,那么您就可以访问 createTarget() 方法。这就是您想要构建转换的地方 。
列表 2. Java 规则类工具
package com.ibm.rsa.cs.extension.sample; import java.util.Iterator; import com.ibm.xtools.cli.model.CompositeTypeDeclaration; import com.ibm.xtools.transform.core.AbstractRule; import com.ibm.xtools.transform.core.ITransformContext; import org.eclipse.uml2.uml.Class; public class ClassKeywordDocRule extends AbstractRule { private static final String NEW_LINE = System.getProperty("line.separator"); |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| public boolean canAccept(ITransformContext context) { Object source = context.getSource(); if (!(source instanceof Class)) return false; Class umlClass = (Class)source; return (umlClass.getKeywords().size() > 0); } public boolean isSourceConsumed(ITransformContext context) { return false; } protected Object createTarget(ITransformContext context) throws Exception { CompositeTypeDeclaration target = (CompositeTypeDeclaration)context.getTarget(); if (target == null) return null; String documentation = target.getDocumentation(); Class sourceClass = (Class)context.getSource(); Iterator keywords = sourceClass.getKeywords().iterator(); while (keywords.hasNext()) { String keyword = (String)keywords.next(); documentation = " _cnnew1@" + keyword + NEW_LINE + documentation; } target.setDocumentation(documentation); return target; } }
执行 createTarget() 方法的第一步,是访问转换此部分的资源以及目标对象。因为在转换处理一个 UML 类时,您已经定义了激活的扩展,所以您可以安全的向一个 Abstract Syntax Tree (AST)访问的 CompositeTypeDeclaration 对象,输入目标对象。
AST 是 C# 元素的模型。所以,一个 C# 程序可以由一个 AST 的实例来代表。例如,一个类可以由一个 CompositeTypeDeclaration 的实例来代表,用 kind 当作 com.ibm.xtools.cli.model.TypeConstants.CLASS。插件 com.ibm.xtools.cli.model 为管理 C# 源代码,提供了所有的 APIs。
如果您打算添加关键字,以作为记录中的一部分,那么,您就必须从获得已处理的记录开始。首先,从已存在的目标中提取已处理过的记录。注意如果没有任何已存在的 C# 源代码,那么在目标对象中就得不到任何记录。在所有的模型元素都被转换完之后,那么新生成的和已存在的代码将会同时出现 。
本文在这里并不讨论关于 AST 的任何细节,除非当扩展需要向生成的代码添加新元素时,才会涉及到一些。通过访问 AST 的方法来做到这一点。对于本例,您想要向类的记录文件添加一个新的标签。对象 CompositeTypeDeclaration 使用一个 String 来储存记录。只要您愿意,您可以编辑该记录文件,并将其设置好 。
为了决定添加什么关键字,从转换内容中访问资源对象,并将其传递给一个 UML 类。从这个对象中,获取关键字的列表(与在执行 canAccept() 方法时您的操作相似)。对于该列表,对关键字进行重复操作,创建一个新的 @keyword 线,以作为记录的前缀 。
方法必须返回一个目标对象,默认条件下,添加规则 thisextension 以作为 targetTransformation 的最终规则(再次参考图 2中的图表)。因此,它处理该转换的“so far”目标。除非扩展规则从目标转换(一个不同 AST 类的转换,或者同一 AST 类的不同对象)中更改了返回元,否则扩展规则不会返回作为目标的同一对象。
这就已经完成了转换扩展的创建以及执行 。
既然已经定义并执行了扩展,那么您就需要测试它。通过创建一次调试配置来进行测试,该调试配置将会在一个新的运行时平台中打开 。
- 为了创建该配置,从主菜单中选择 Run > Debug。
- 在对话框中,创建一个新的 Eclipse Application 配置,并给它起一个合适的名字。
- 您可以改变工作区的位置:选择一个新位置,以避免无意识中影响到一个已存在的工作区,这是一个明智的做法。
- 其余的默认设置是可以接受的(图 9)。
- 当您完成编辑配置以后,按下 Debug 按钮以启动一个 Eclipse 的新实例。
该新实例,将会把转换扩展(您刚刚创建的)当做一个插件安装。
为了测试扩展,您将需要创建一个新的 UML 项目,并向新的 Eclipse 内核的实例,引入一个 Visual Studio C# 项目。您也可以在创建一个新转换配置时,通过点击 Create New Target Container按钮来引入 Visual Studio C# 项目。
- 在 UML 模型中,创建一个测试包和类。结果得到的工作区应该和图 10 所示的相似。
接下来,您需要向类添加一个关键字,因为您的扩展,只会处理那些有一个已定义关键字的类。
- 选择类(要么在图表中要么在 Project Explorer 项目中),然后在 Properties 试图中选择 Stereotypes 子标签。
- 在 Keywords 区域输入一些文本,如图 11 所示。
要设置文本项目以及模型,您需要创建一个新转换配置,该配置定义了 UML 到 C# 转换的主要参数。
- 从主菜单中选择 File > New。
- 然后,在 Transformations 目录下,选择一个新的 Transformation Configuration 并点击 Next,如图 12 所示。
这里有许多 Rational Software Architect 中包含的转换类型。
- 选择 UML to C# 转换,因为这是您需要为之而创建的扩展。
- 给它起一个合适的名字,如图 13 所示(该名字将在 UML 项目中用做配置文件的文件名)。
- 在一个转换配置中,您需要指定的第一件事,是资源模型以及目标项目。确保选择了 Models 文件夹下的 UML 模型,而不是实际的 .emx文件。
- 通过点击 Create New Target Container 按钮来创建目标,如图 14 所示。
这将启动如图 15 所示的 Net Solution Import 向导。
- 确保在 VS 2005 中打开了 .NET Solution,并使用引入向导,来向 Rational Software Architect 工作区引入 .NET Solution 。
- 使用 Browse 按钮,来选择合适的要被引入的 Visual Studio C# 项目。一旦引入 Visual Studio C# 项目,那么它将会在目标列表中显示出来。
- 为转换选择引入的 C# 项目作为 Selected target(图 16),并点击 Next。
在这里您并不会深入到其他转换配置选项的具体细节中。
- 点击 Finish 按钮以创建转换。
既然配置已经被创建起来,那么现在就可以激活它。从该项目的生命考虑,它并不需要被重新创建。
- 为了激活转换以及您对它所做的扩展,在 Project Explorer 视图中右击转换配置,并选择 Transform. > UML to C#(图 17)。
- 为了检查转换的结果,切换至 Visual Studio IDE(图 18)。您可以看到,在类的记录文件中,怎样添加一个关键字。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14780873/viewspace-586740/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/14780873/viewspace-586740/