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

developerWorks 中国  >  Rational | Open source  >

实现 UML 模型的自动化比较及合并:通过在 IBM Rational 软件交付平台上运行一个 Ant 任务

通过命令行在两个 UML 模式之间生成一个变更列表

developerWorks
文档选项

未显示需要 JavaScript 的文档选项

英文原文

英文原文


级别: 中级

Natalia Balaba-Liaskovski, 软件工程师, IBM

2008 年 10 月 31 日

学习如何创建和调用一个能够在headless 操作(命令行)模式中运行从而在两个 UML 模式之间生成一个变更列表的 Ant 任务。先决条件:这些工具都必须是 7.0.0.5版本: IBM® Rational® Application Developer,IBM® Rational® Software Architect, 或者 IBM® Rational® Software Modeler。

IBM® Rational® Software Architect 以及它的相关产品(参见说明) 为小组的模型驱动开发(MDD)以及平行开发提供强有力的 UML 建模技术。这些包括转换和比较-合并技术。

注释:
在这篇文章中,“Rational 软件”表示这些产品中的任何一个:Rational® Software Architect, Rational® Application Developer, 或者 Rational® Software Modeler。

这里有几种情形,对通过命令行工具在模型之间产生差别列表是十分有利的,在一个构建过程或者当量中或许只是作为一个步骤。例如:

  • 在一个模型当量的任何一点,都可能选择两个版本——或许是最新的版本和在先前构建基线的版本——为发布到 Wiki 或者其它 Web 网页进行浏览产生一个差异列表。
  • 在简单的 ad hoc 建模中,可能要在各自独立的开发模型中运行这个过程,且这两个模型拥有类似的结构并演化成共享的语义数据,比如有相同名称的类和角色。此外,有了合并这些模型可以用这种方式来比较。
  • 在高级的模型驱动开发情景中,一个软件构架可以调解使一个演化模型与一个生成的演化码基线一致,从 Java 到 UML 转换能力可以产生一个可以与原始源代码一致并可以与之比较的模型,从而创建和发布这个浏览列表。

这篇文章主要研究 MDD 情形,因为这很可能就是这个技术所需要的情形。而在其它 情形采用此技术则相对比较直接。

在代码和模型之间产生差量列表的选项

根据这个项目规模的大小,主模型的变更可来自多个开发人员。一个构件可能需要在将它们引入到主模型之前浏览来自单个贡献者的变更设置。通常情况下,这是由一个转换来完成的,比如 Java-to-UML。这个转换会产生一个反映 Java 代码当前状态的 UML 模型。要查看主模型和一个源自此代码的模型之间的区别,可以采取几种方式来实现。

方法之一是将这个目标转换输出作为这个主模型。在 Rational 软件环境中运行此转换将会启动一个可视的结构合并会话(正如 融合 ——请参见下面的 Note),这样可以在把它们应用到主机(目标)模型之前展现一个变更列表。这种方法将会在委托此结构合并会话之上修改这个主模型。

注释: 融合 (一个 结构对比)是一项仅仅利用合格的名称来对照模型的技术,并且为在模型之间或者结构变更提供一个机制,而且无论这些模型是否共享一个始祖。它还受到合并模型命令的刺激。融合广泛地应用于 MDD 中 调整工作流程

然而,这项技术却不能自动从命令行中产生。相反,这个合并技术(请参见下面的 Note)却可用来将这个问题转换为身份的对照。一个生成的模型可以保存到一个位置标志符(一个空白模型),与主模型合并,然后对照会话就可以运行,从而创建一个变更列表(请参见图 1)。这个合并工具和身份对照技术都允许自动化和命令行的调用。

注释: 模型 联合就是一项可以改善目标模型的元素身份使其与源模型中相同的元素相匹配的技术。它利用精密的身份匹配器来产生在稍后的模型中可以匹配的关键元素,这样以来这些元素 ID 就可以向前移动。这样就有效地在这些模型之间创建了一个始祖关系,它们似乎都是直接从一个到另一个这样演化而来的。这样利用这篇文章中所描述的方法就可以使它们变得具有可比性。


图 1. 两个连接模型的比较会话
变更列在左边,合并结果视图在右边

图 2 显示了在这些模型之间的可视化合并过程中,当点击 Save deltas 按钮时这些差量列表是如何保存的。假设这个标识必须从一个可视化会话中产生,并且由于要剖析这个文件从而创建更多精致的浏览工具十分困难,就会采用可替换机制和文件格式。


图 2. Delta 记录文件内容
屏幕输出

运行一个 Ant 任务实现自动化

这种方法是由一个 Apache Ant 任务实现自动化的。Ant 任务可以从命令行开始以批量处理模式运行,这样可以产生一个变更列表并将它们保存到一个文件中。此外,生成的变更列表可以以可导向模式保存。Compare Merge 中的功能可以下载这样的文件到 Rational 软件并用 Delta Annotation Viewer 来浏览它们,如图 3所示(请参见资源,可学习更多的关于 deltas 的知识)。


图 3. Delta 注释浏览器
ModelDeltas 页签

创建一个 Eclipse Ant 项目

假设这样的情景:

  • 一个 Java-to-UML 转换必须运行从而产生 UML 模型。
  • 这个模型必须保存,与一个主模型保持一致,那么这两个模型就必须相互比较。
  • 两个模式之间的差异表稍后需要保存进行评审。
  • 使这项工作在批量(headless 操作)模式中运行。

要满足这些需求,您将创建一个您可以通过命令部署的 Ant 任务类。

  1. 首先,创建一个样本 Eclipse 插件,如图 4 所示。(您可以在 com.acme.headless.ant_1.0.0.jar 找到带有源代码的完整的插件)。

图 4. 创建这个 headless 操作模式的 Ant 插件
Package Explorer 视图

  1. 将显示在列表 1 中的依存关系添加到这个清单文件中。

列表 1. 依存关系添加到这个清单文件中
				
  Manifest-Version: 1.0
  Bundle-ManifestVersion: 2
  Bundle-Name: Ant Plug-in
  Bundle-SymbolicName: com.acme.headless.ant;singleton:=true 
  Bundle-Version: 1.0.0 
  Bundle-Activator: com.acme.headless.ant.Activator
  Bundle-Vendor: ACME
  Bundle-Localization: plugin
  Require-Bundle: org.eclipse.ui,
  org.eclipse.core.runtime,
  org.eclipse.ant.core,
  org.apache.ant,
  org.eclipse.gmf.runtime.emf.core.compatibility,
  com.ibm.xtools.transform.core,
  com.ibm.xtools.uml.core, 
  com.ibm.xtools.uml.msl,
  com.ibm.xtools.comparemerge.modelconverter,
  com.ibm.xtools.comparemerge.delta.annotation.ui,
  com.ibm.xtools.comparemerge.core
  Eclipse-LazyStart: true

  1. 创建一个如列表 2所示的 Differences Logger 类,并添加一些属性到这个类。公共属性将会被当作 Ant 任务参数使用。

列表 2. 创建一个附加属性的 Differences Logger 类
				
package com.acme.headless.ant.task;

public class DifferencesLogger extends org.apache.tools.ant.Task {
// ant task parameter variables
// absolute path to transformation configuration (.tc) file
public String transformConfigPath; 
// absolute path to the master model to be compared to
public String masterModelPath; 
// absolute path to the auto-generated changes log (the file does not have pre-exist) 
public String deltaLogFileName;
// absolute path to a blank model template
public String blankModelPath; 

// private members
private String tempModelName = "HTBlankModel"; //$NON-NLS-1$
private URI tempModelURI = null;
}

  1. 现在创建这个任务execute()方法(请参见列表 3)。

列表 3. 创建 execute() 方法
				
/*
* Execute task 
* (non-Javadoc)
* @see org.apache.tools.ant.Task#execute()
*/
public void execute() throws BuildException {

try {
// load transformation configuration file
IFile file = 
ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(
new Path(transformConfigPath));
ITransformConfig config = TransformConfigUtil.loadConfiguration(file);

//prepare Java to UML transformation forward context by switching its target container 
to point to a temporary, empty model file 
ITransformContext forwardContext = createTarget(config);
//execute transformation
IStatus status = 
TransformController.getInstance().
execute(config, forwardContext, false, true, null);

System.out.println("Completed transform execution, status = " + status.getMessage()); 

if (status.getCode() == IStatus.OK) {

// instantiate model alignment facade
ModelConverterFacade mc_facade = new ModelConverterFacade();

//verify that master copy does exist
File baseFile = new File(getMasterModelPath());
if (!baseFile.exists()) {
System.out.println("Invalid master copy path: " + getMasterModelPath()); 
System.out.println("Please correct the parameter and re-run the script"); 
return;
}

// obtain model file created by transformation. Verify it exits
File contributorFile = new File(getTemporaryModelURI().toFileString());
if (!contributorFile.exists()) {
System.out.println("Error during transformation: failed to create target file"); 
System.out.println("Verify that " + contributorFile.getParent() + " is not read-only”); 
return;
}

// align master and contributor files
if (!mc_facade.alignSingleModelFile(baseFile, contributorFile, null, contributorFile)) 
{
System.out.println("Error during model alignment"); 
System.out.println(contributorFile.getAbsolutePath() + " should exist!"); 
return;
}
// compare aligned models and save changes log
compareWithEachOther(baseFile, contributorFile);
} 
} catch (Exception e) {
e.printStackTrace();
System.out.println("Failed execution" + e.getLocalizedMessage()); 
}
}

  1. 在 com.acme.headless 插件中创建一个 plugin.xml 文件,并宣布这个 Ant 任务(列表 4)。

列表 4. 创建一个 plugin.xml 文件并声明这个 Ant 任务
				
<extension
point="org.eclipse.ant.core.antTasks">
<antTask
class="com.acme.headless.ant.task.DifferencesLogger"
library="delta_logger.jar"
name="diff_logger">
</antTask>
</extension>

  1. 更新如列表 5所示的这个插件的构建属性。

列表 5. 更新这个插件的构建属性
				
bin.includes = META-INF/,\
delta_logger.jar,\
plugin.xml
source.delta_logger.jar = src/
output.delta_logger.jar = bin/

  1. 右键点击这个 plugin.xml 文件,并通过选择 PDE Tools > Create Ant Build File 来创建一个 Ant build.xml 文件(请参见图 5)。


图 5. 创建 Ant 构建文件
下拉菜单显示了所描述的选择

  1. 右键点击这个 build.xml 文件并选择 Run As > Ant Build 。这样将会在这个插件根目录中创建一个 diff_logger.jar 文件。
  2. 最后,如图 6 所描述的那样,在 Project Explorer 中,选择这个 com.acme.headless.ant 插件并点击下拉菜单上的 Export ,从而将它导入 Rational 软件插件目录中(C:\Program Files\IBM\SDP70\plugins, typically):作为一个可部署的插件(com.acme.headless.ant_1.0.0.jar)。

图 6. 导入这个 com.acme.headless.ant 插件
显示插件,然后导出所选择的

安装运行环境

要阐述这个步骤,我们已经在附加的 Projects.zip 压缩文件中提供了三个案例(请参见 下载)。按照下列这些步骤来使用这三个项目:

  1. 使用现存的工作空间(C:\targets\my-workspace)。或者创建一个新的工作空间。
  2. 启动您的 Rational 软件来使用 C:\targets\my-workspace 。
  3. 将这些文件从 Projects.zip 压缩文件中解压出来,并将这三个项目 Import 到您的工作空间。
  4. 转到 AntRunnerPlugin 项目 并右键点击这个 plugin.xml 文件。然后选择 PDE Tools > Create Ant Build File 。这样将产生一个 build.xml 文件。
  5. 打开这个 build.xml 文件并对它进行编辑,如图 6所示的那样来添加最后的目标。
    1. 第一个参数(transformConfigPath) 指向 Java-to-UML 转换配置文件。
    2. 这个masterModelPath参数指向您的基本 UML 模型的位置。这个模型将不会被这个任务改写。
    3. 这个deltaLogFileName参数指向产生的变更日志文件的未来的位置(它先前并不一定存在,并不一定在这个工作空间)。
    4. 这个blankModelPath 参数指向这个任务所使用的一个空模型模版的位置,因为它仅仅被用来作为模版。这个模版可以是任何一个空模型,但是您可以利用它提供便利的案例。

列表 6. 编辑这个 build.xml 文件从而添加最后的目标
				
<target name='mytest'>
< diff_logger
transformConfigPath='C:\targets\my-workspace\Java Project\J2UML.tc'
masterModelPath='C:\targets\my-workspace\Model Project\Blank Model.emx'
deltaLogFileName='C:\targets\my-workspace\Model Project\changes_log.xml'
blankModelPath='C:\targets\my-workspace\Model Project\template\EmptyModel.emx'
/>
</target>
      

  1. 更新这个默认的任务(Ant 构建文件的第一行)为mytest 任务
<project name="AntRunnerPlugin" default="mytest" basedir=".">

注释:
确保 C:\targets\my-workspace 是由您工作空间的真实位置所代替的。

  1. 保存这个修改的 Ant 构建文件。

运行环境现在已经安装,这个任务可以在 Rational 软件中,也可以在 headless 操作模式中运行。

  1. 要在 Rational 软件中运行这个 Ant 任务,请选择 build.xml 文件,右键点击,然后选择 Run As > Ant build
  2. 注意在 Model Project 中有一个叫做 changes_log.xml 的新文件。可以通过选择 Window > Show View > Other > Model Delta Annotation Viewer > Model deltas ,在这个 delta 日志浏览器(图 7)中复制这个文件。

图 7. 在 delta 注解浏览器中查看变更。
在最上方的 build.xml 页签,在底部的 ModelDeltas 页签

  1. 简单地将生成的这个文件拖拽到这个浏览器上。

这个 EMF 层级 deltas (单个的变更), 显示在叶节点,可以在 UML 层级很方便地归到复核的 deltas 中。这些复合构件代表姿势或者其它逻辑分类(比如一个拖拽-放下复合对象图解,这将导致一个组位置变更,包裹-相关变更,比如变更到特定的包裹复合 delta,等等)。

在 headless 操作模式中运行这个任务

  1. 记住您的 Ant build.xml 文件的绝对位置,并将这个 runant.bat 文件从列表 7 复制到您的 Rational 软件的根文件夹中(比如, C:\Program Files\IBM\SDP70)。

列表 7. runant.bat 文件
				
setlocal
REM RUNANT_DIR=This directory (which may, or may not, be your current working directory)
set RUNANT_DIR=%~dp0

set debug=
if not '%1' == 'debug' goto studio
set debug=-Xdebug -Xnoagent -Djava.compiler=none ^
-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000

:studio
REM The root directory of your Studio installation
set STUDIO_DIR=C:\Program Files\IBM\SDP70
if not exist '%STUDIO_DIR%'\jdk\jre set STUDIO_DIR=%RUNANT_DIR%..\..\..
if not exist '%STUDIO_DIR%'\jdk\jre echo 
ERROR: incorrect STUDIO_DIR=%STUDIO_DIR%
if not exist '%STUDIO_DIR%'\jdk\jre goto done

:java
if not $%JAVA_DIR%$==$$ goto workspace
set JAVA_DIR=jdk\jre\bin
:workspace
if not $%WORKSPACE%$==$$ goto check
REM #######################################################
REM ##### you must edit the 'WORKSPACE' setting below #####
REM #######################################################
REM *********** The location of your workspace ************
set WORKSPACE=C:\targets\my-workspace
:check
REM ************* The location of your workspace *****************
if not exist '%WORKSPACE%' echo ERROR: 
incorrect workspace=%WORKSPACE%, edit this runAnt.bat and correct the WORKSPACE envar
if not exist '%WORKSPACE%' goto done

set LOCATIONS=-DSTUDIO.DIR=%STUDIO_DIR% -DSTUDIO.RUNANT=
%RUNANT_DIR% -DSTUDIO.WORKSPACE=%WORKSPACE%

:run
@echo on
'%JAVA_DIR%\java' -cp '%STUDIO_DIR%\startup.jar' 
%debug% org.eclipse.core.launcher.Main 
-debug -application org.eclipse.ant.core.antRunner -data 
'%WORKSPACE%' -file %WORKSPACE%\AntRunnerPlugin\build.xml

  1. 打开并编辑这个文件,从而将具体的路径映射到您的环境中。这些都非常重要的路径:
    • STUDIO_DIR: 您的 Studio 安装的根目录(例如, C:\Program Files\IBM\SDP70)
    • JAVA_DIR: 绝对或者相对批量文件位置 Java Runtime Environment,或者 JRE(例如, jdk\jre\bin)
    • WORKSPACE: 您的 Rational 软件工作空间的位置(通常是,C:\targets\my-workspace)
    • 批量文件最新的命令行: 您的 build.xml 文件位置与您的工作空间相互关联(比如, AntRunnerPlugin\build.xml)
  2. 修改这个任务路径,使其指向 build.xml 文件位置,这个文件是在 Step 4 中产生的。
  3. 运行从本地命令行到批量文件位置的 antRun.bat 文件。这个结果应该与 Step 6 中的一样。

改编一个客户的转换

  1. 创建一个 Java-to-UML 转换(或者采用一个现存的转换)。
  2. 配置它并保存到这个配置文件。
  3. 修改这个在先前步骤中生成的 build.xml 文件,使其指向您的配置文件(请参见 transformConfigPath 参数)。
  4. 修改这个masterModelPath参数,使其指向您的主模型文件(这个文件将不会被改写)。
  5. 修改这个deltaLogFileName参数使其指向 delta 日志文件的位置。
  6. 修改这个blankModelPath变量使其指向这个空白的(空的)模型模版(这个文件将不会被改写)。
  7. 在先前的例子中运行这个 Ant 任务。


参考资料

学习

获得产品和技术

讨论


关于作者

Natalia 是一位支持 IBM Rational 软件工具的软件工程师。




对本文的评价










回页首


IBM 和 IBM 标志都是美国,其它国家或者两者中 International Business Machines Corporation 的商标。 Java 和所有基于 Java 的商标和标志都是美国,其它国家,或者两者中 Sun Microsystems 公司的商标。 其它公司,产品和服务名称都可以是商标或者其它服务标识。 其他公司、产品或服务的名称可能是其他公司的商标或服务标志。

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