扩展 UML 到 C# 转换

简介

IBM® Rational® Software Architect 包含了一系列的预定义转换。其中的一些用于将一个 UML 模型转化为源代码。UML 到 C# 转换,如同其他一些模型到代码转换一样,可以被扩展。本篇文章列出了创建一个简单的扩展示例所需的步骤,该扩展示例演示了此功能的核心能力。

对于 Rational Software Architect 的大多数特性,您要使用标准 Eclipse 扩展机理,创建一个插件和执行特定扩展点来扩展它。本篇文章并没涉及到一般的插件开发,如果您需要这方面的更多信息,您可以查看本文的 参考资源 部分。但是,本文包括了创建以及测试一个转换扩展,所需要的一些插件开发技巧,并将重点放在自定义 C# 转换上 。

您需要扩展转换的原因

下面列出的,是您想要扩展转换可能的几个原因,您可能想要:

  • 向您的方法添加自动记录,记录什么列出参数以及返回类型。
  • 向每一个产生的类型添加作者信息。
  • 更改转换产生的默认方法主体。

在每一种情况下,扩展转换都能帮助您,生成您自定义的资源。

开始

如图 1 所示,当一次 UML 到 C# 转换启动时,它从配置作为转换资源的 UML 模型开始。


图 1. 总体转换结构
UML 到 C# 转换元素

该转换处理整个模型,如图 2 所示。转换浏览了资源,并组成了一个 C# Abstract Syntax Tree(AST),而这又是另外一个 Eclipse 建模框架(EMF)模型。然后转换使用 Java Emitter Template 2 (JET2),来将 AST 转换成 C# 资源 。在本文的结尾,您可以找到目标的一个完整列表。


图 2:配置转换扩展元素
UML 模型

对于这个简单的示例,您将定义一个简单的,类层次的扩展,每当一次转换转换将一个 UML Class 元素转化成 C# 源文件时,都会激活该扩展。本扩展仅仅搜寻为该类定义的关键字,然后使用它们,来添加与源代码中的类相关的新记录标签。

您需要执行的总体步骤包括:

  1. 为您的转换扩展创建一个新的插件项目。该项目可以与其他的扩展联合起来。但是,为了让这个例子变得简单,您需要从头开始创建一个新的项目。
  2. 添加一系列需要的插件附件。这些插件定义了您正在运行的扩展点,并提供了激活扩展您将需要的 APIs。
  3. 在插件描述器中,定义能识别您将要扩展的转换的扩展点,以及您想要做出更改的其中的点。如果您想要得到关于一个扩展点定义(以及怎样去构建它)的更多具体信息,参见 参考资源 部分中的 有关 Eclipse Plug-in Architecture 的说明(Notes on the Eclipse Plug-in Architecture)部分。
  4. 提供一个 Keyword Documentation Rule 的 Java 工具,每当转换遇到您注册的元素类型时,都会使用到该工具。
  5. 通过启动一个运行时工作台,并执行一次 UML 到 C# 转换,来测试转换。

    创建并配置一个新的插件项目

    您的转换扩展从一个新的插件项目开始。

    1. 选择 File > New > Project
    2. 从项目类型列表中选择 Plug-in Project,然后点击 Next
    3. 在 New Plug-in Project 向导的第一个页面中,输入一个有效的项目名。插件的 Eclipse 惯例,是使用一个如图 3 所示的 URI 域。

    图 3. New Plug-in Project 向导
    属性设置以及目标平台
    1. 在第二个界面中(图 4),您应该更改默认的 Plug-in Name 区域。输入 Sample UML to CS Extension.。其他默认的设置可以接受。

    图 4. New Plug-in Project 向导属性页面
    插件属性以及选项

    在最后的页面中,不需要选择一个插件模板,因为那里没有为转换扩展准备的模板,只有新完成的转换。

    1. 清除模板选项并点击 Finish,如图 5 所示。

    图 5. New Plug-in Project 向导最后的页面
    可用模板的列表

    当向导设置完成后,一个新创建的插件项目会生成,并且项目描述器的 Overview 页面会打开,如图 6 所示。


    图 6. 新项目结构
    左边的 Package Explorer, 右边的概述

    接下来的一步,是添加作为附件的一些插件(在切换至 Plug-in Development 视角以后)。这些插件包含了扩展点定义,您将为该点定义提供一个工具,以及在扩展工具中将会用到的 APIs。

    1. 切换至附件标签(在编辑器的底部可以找到它),并添加作为附件的如下插件。
      • com.ibm.xtools.modeler
      • com.ibm.xtools.transform.core
      • com.ibm.xtools.transform.uml2.cs
      • com.ibm.xtools.cli.model

    结果得到的列表应该与图 7 相似。


    图 7. 独立的插件
    窗口底部的标签 

    定义并运行扩展

    接下来要讲的一步,是您将要向一个或多个扩展点提供的工具。

    1. 切换至 Extensions 标签。
    2. 点击 Add 按钮以添加一个新扩展。对话框如图 8 所示。
    3. 输入扩展点 com.ibm.xtools.transform.core.transformationExtensions
    4. 当找到它时,选中它并点击 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 子元素(为每一个扩展转换的类型)。这些元素中的每一个,都定义了扩展哪一个转换。

    1. 对于这个简单的例子,用 IDcom.ibm.xtools.transform.uml2.cs.internal.UML2CSTransform. 来指定 targetTransformation
    2. 您应该为 ID,版本号,名字,以及可用 Boolean 值应用合适的值。

    每一个转换扩展,将子元素定义为一个规则定义,它指定了执行规则界面的类。该类完成了构建转换的大多数工作,提供了放置您自定义的过程逻辑的地方。它作为一个单独的元素定义,因为对于一个单独的类来说,构建转换的大多数部分(也就是类,属性,以及操作)是可能的。

    一旦定义了所有的规则,它们将与 ExtendTransform. 元素一起构建的转换的一部分协调起来。该元素定义了规则要构建转换的一部分。换句话来说,一旦规则被创建,我们需要指定什么时候去使用它们 。

    对于这个简单的例子,每当一个新类被转换时,您都要构建转换 。targetTransform. 的值应该是 com.ibm.xtools.transform.uml2.cs.internal.ClassTransform。目标转换 ID 的完整列表,可以在本文结尾的 附录 段落中找到。

    因为不止一个规则可以构建转换的任意一个特殊部分,所以把它们集中到这里,作为 ExtendTransform. 元素的子元素。可能您在您的项目中只有一个定义的规则,所以这里有一个清晰而简单的映射 。在各种插件的条件下(或者 transformationExtensionsTransformExtensionRuleDefinitionExtendTransform,或者 AddRule 元素的多种实例), 制作一个与图 2相似的图表,将是有帮助的。元素 RuleDefinition id 必须与元素 AddRule 的 id 相匹配。

    当您完成您的编辑之后,保存文件。您应该注意到,在文件 plugin.xml 靠近线的左部边缘区域,有一个很小的错误图标,该文件指定了执行类。这意味着在项目中不能找到该类。您可以启动 New Class 向导,并使用它来创建类文件。您也可以使用 File > New 菜单手动创建该类。

    1. 不管您以何种方式在 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 类的不同对象)中更改了返回元,否则扩展规则不会返回作为目标的同一对象。

    这就已经完成了转换扩展的创建以及执行 。

    测试扩展

    既然已经定义并执行了扩展,那么您就需要测试它。通过创建一次调试配置来进行测试,该调试配置将会在一个新的运行时平台中打开 。

    1. 为了创建该配置,从主菜单中选择 Run > Debug
    2. 在对话框中,创建一个新的 Eclipse Application 配置,并给它起一个合适的名字。
    3. 您可以改变工作区的位置:选择一个新位置,以避免无意识中影响到一个已存在的工作区,这是一个明智的做法。
    4. 其余的默认设置是可以接受的(图 9)。


    图 9. 新调试配置
    左边的树状图,右边的标签

    1. 当您完成编辑配置以后,按下 Debug 按钮以启动一个 Eclipse 的新实例。

    该新实例,将会把转换扩展(您刚刚创建的)当做一个插件安装。

    为了测试扩展,您将需要创建一个新的 UML 项目,并向新的 Eclipse 内核的实例,引入一个 Visual Studio C# 项目。您也可以在创建一个新转换配置时,通过点击 Create New Target Container按钮来引入 Visual Studio C# 项目。

    1. 在 UML 模型中,创建一个测试包和类。结果得到的工作区应该和图 10 所示的相似。


    图 10. 运行时工作台中的测试项目
    右边的配置板,左边的视图

    接下来,您需要向类添加一个关键字,因为您的扩展,只会处理那些有一个已定义关键字的类。

    1. 选择类(要么在图表中要么在 Project Explorer 项目中),然后在 Properties 试图中选择 Stereotypes 子标签。
    2. 在 Keywords 区域输入一些文本,如图 11 所示。


    图 11. 设置关键字属性
    顶部的图表, 底部的标签以及数据

    要设置文本项目以及模型,您需要创建一个新转换配置,该配置定义了 UML 到 C# 转换的主要参数。

    1. 从主菜单中选择 File > New
    2. 然后,在 Transformations 目录下,选择一个新的 Transformation Configuration 并点击 Next,如图 12 所示。


    图12. 创建一个新的转换配置
    从列表中选择一个向导

    这里有许多 Rational Software Architect 中包含的转换类型。

    1. 选择 UML to C# 转换,因为这是您需要为之而创建的扩展。
    2. 给它起一个合适的名字,如图 13 所示(该名字将在 UML 项目中用做配置文件的文件名)。


    图 13. 选择转换
    树状图中的前置转换列表

    1. 在一个转换配置中,您需要指定的第一件事,是资源模型以及目标项目。确保选择了 Models 文件夹下的 UML 模型,而不是实际的 .emx文件。
    2. 通过点击 Create New Target Container 按钮来创建目标,如图 14 所示。


    图 14. 选择资源并创建转换的目标
    左边的资源, 右边的目标

    这将启动如图 15 所示的 Net Solution Import 向导。

    1. 确保在 VS 2005 中打开了 .NET Solution,并使用引入向导,来向 Rational Software Architect 工作区引入 .NET Solution 。


    图 15. 引入 .NET solution
    输入方案文件路径

    1. 使用 Browse 按钮,来选择合适的要被引入的 Visual Studio C# 项目。一旦引入 Visual Studio C# 项目,那么它将会在目标列表中显示出来。
    2. 为转换选择引入的 C# 项目作为 Selected target(图 16),并点击 Next


    图16. 选择转换目标
    左边的资源以及右边的目标

    在这里您并不会深入到其他转换配置选项的具体细节中。

    1. 点击 Finish 按钮以创建转换。

    既然配置已经被创建起来,那么现在就可以激活它。从该项目的生命考虑,它并不需要被重新创建。

    1. 为了激活转换以及您对它所做的扩展,在 Project Explorer 视图中右击转换配置,并选择 Transform. > UML to C#(图 17)。


    图 17. 激活转换
    菜单命令

    1. 为了检查转换的结果,切换至 Visual Studio IDE(图 18)。您可以看到,在类的记录文件中,怎样添加一个关键字。


    图 18. 生成代码的结果
    左边的代码,右边的树状图

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14780873/viewspace-586740/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/14780873/viewspace-586740/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值