月度归档:2008年09月

ClearQuest二次开发

ClearQuest API概述

Rational ClearQuest 是重要的变更管理工具,Rational ClearQuest 更能让客户根据自己的具体需求,灵活的设计变更管理流程。除此之外,Rational ClearQuest 还提供了一套编程接口,即 Rational ClearQuest API,让用户和开发人员可以根据需要通过编程来实现 Rational ClearQuest 的相关功能,同时还可以通过编程来实现模式中 Hook 脚本的开发和定制,从而使整个 Rational ClearQuest 产品的功能更加灵活和强大。
通过CQ的二次开发接口,我们可以更灵活的定义自己的统计,或是使用脚本来批量修改CQ中的MR。
ClearQuest API 提供了VBS实现和Perl实现。也就是说可以使用VBS或Perl进行CQ的二次开发,两种开发方式提供了完全一致的开发接口。同时由于VBS是用过调用COM来使用CQ接口,理论上可以使用其他开发语言通过直接调用COM的方式来使用CQ的API。
由于VBS和COM都为MS的专有技术,VBS的脚本只能在windows平台上执行,Perl脚本则可以实现跨平台。 相比VBS,Perl的使用面更广,功能也更为强大,且考虑到Perl的跨平台性,使用Perl进行CQ的二次开发会是一个比较好的选择。

Perl语言基础知识

需要使用CQ的API需要先安装CQ的客户端。CQ的客户端有带一个专供CQ使用的perl引擎,cqperl,在运行perl脚本时候直接使用cqperl xx.pl运行。
考虑到熟悉Perl的用户并不多,在介绍CQ API前先对Perl的相关语法等做个简单的介绍。这里只提供基础的入门介绍,以便perl程序的阅读,如需要更深入的了解请阅读参考中的相关文档。

基本语法

perl里面语句也是用“;”来分开的。注释使用“#”。

变量符号
  • 标量定义,以$号开头,如:$num =1;
  • 数组定义,以@开头,如:@array = (1,2,3);
    数组元素调用 @array[index],其中index表示数组下标,如上例,@array[0]的值是1

  • 散列定义,以%开头,如:%hash=("a",1,"b",2);
    散列调用 %hash,其中key表示键值,如上例,%hash{"b"}的值是1

变量范围
  • $xx什么都不写,表示全局变量。整个文件中都可以访问到;
  • local $xx 表示局部变量,但是这个值可以被其调用的子程序访问到
  • my $xx 表示局部变量,只能在这一个函数里面可以使用,子程序就不能使用
函数定义
sub FunctionName
{
local ($a,$b)=@_;
return “”;
}

注意: 函数后便没有(),也没有参数列表定义。也就是说,他接受任何形式的参数,以数组的方式传递过来。所以内部使用的话,就用@_这个默认当前参数来取之。

操控语句(语法)
  • 除" " "0"(空字符,0),以外都为真。
  • if/while/until/for等语法类似c/cpp/java
  • 使用foreach进行遍历。

    foreach $user (@users) {
    do something...
    }

  • 跳出控制结构: next 和 last。next跳过当前操作,进入下一循环。last直接跳出循环。
  • perl包含文件。具体说明参考Perl中的文件包含(do, require, use)

ClearQuest API使用说明/范例

连接CQ库

CQ的数据存储在数据库(用户数据库)中,我们公司使用的是SQL Server。虽然可以通过直接访问SQL Server数据库的方式获取MR信息,但由于数据库的表结构复杂且受权限的约束(没有开放写权限),很多时候直接访问数据库并不是一个好主意。
在使用CQ API时,首先要做的是和CQ建立session,连接上CQ的库(模式库)。主要步骤为:

  • 创建session对象

    my $session = CQSession::Build();

  • 登陆CQ库

    $session->UserLogon(login_name, password, database_name, database_set);
    • login_name 登陆的用户名,也就是使用CQ客户端登陆的用户名。
    • password 用户密码,同CQ客户端登陆的密码。
    • database_name 库名
    • database_set 库集。
  • 操作完成后关闭session。

    CQSession::Unbuild($session);

  • 创建查询

    在成功建立session后就可以对CQ库进行操作了。
    创建查询的主要步骤如下。

    • 创建Query对象。

      my $queryDef = $session->BuildQuery(entitydef_name);
      • entitydef_name 这个就是在CQ客户端创建查询时候选择的record type。
    • 设定需要返回的字段(同CQ客户端上选择的输出字段)。

      $queryDef->BuildField("id");#id
      $queryDef->BuildField("Headline");#标题
      ......

    • 创建查询条件。
      • 创建查询条件对象。

        my $operator = $querydef->BuildFilterOperator(bool_operator);
        • bool_operator 这个为逻辑条件。常用的逻辑条件如:$CQPerlExt::CQ_BOOL_OP_AND(与) $CQPerlExt::CQ_COMP_OP_EQ(等于)
      • 为查询对象,设置过滤条件。

        $operator->BuildFilter(field_name, comparison_operator, value);

      • field_name 进行过滤的字段名,同CQ客户端中设置的过滤条件字段。
      • comparison_operator 逻辑判断条件。$CQPerlExt::CQ_COMP_OP_EQ 等。
      • value 该字段的值
  • 创建结果集

    my $resultSet = $session->BuildResultSet($queryDef);

  • 执行查询,获取查询结果
    • 执行查询

      $resultSet->Execute();

    • 遍历,获取查询的结果集的值。

      while (($resultSet->MoveNext()) == 1)
      {
      my $mr_id=$resultSet->GetColumnValue(1);
      }
      • 使用$resultset->GetColumnValue(columnNum);获取字段的返回结果,其中columnNum为返回字段的序列,由1开始。

    编辑MR

    除获取MR外,对MR进行一些编辑也是常用的操作。编辑MR主要需要以下操作。

    • 获取需要编辑的MR对象

      $session->GetEntity(entity def_name, display_name);
      • def_name 这里同BuildQuery的参数类似

      • display_name 这里填写MR ID
  • 编辑对象

    $session->EditEntity(entity, edit_action_name);
    • entity 需要编辑的对象
    • edit_action_name 编辑操作的名称,(例如: "modify" or "resolve")
  • 设定字段的值

    $entity->SetFieldValue(field_name, new_value);
    • field_name 字段名称
    • new_value 修改后的值
  • 提交/回滚修改
    • 提交 $entity->Commit();

    • 回滚 $entity->Revert();

  • 完整范例

    在这个范例中,将查找出在dbname里Product为prd10000且Verified的MR,并将其Close。

    use CQPerlExt;
    ###连接CQ###
    my $loginName = "loginName";
    my $loginPassword = "loginPassword";
    my $databaseName = "dbname";
    my $databaseSet = "dbset";
    my $session = CQSession::Build();
    $session->UserLogon($loginName, $loginPassword, $databaseName, $databaseSet);

    ###创建查询,查询出需要close的MR###
    my $queryDef = $session->BuildQuery("Dev_Defect");
    $queryDef->BuildField("id");#id
    my $operator1 = $queryDef->BuildFilterOperator($CQPerlExt::CQ_BOOL_OP_AND);

    @Product = ("%prd10000%");
    $operator1->BuildFilter("Product", $CQPerlExt::CQ_COMP_OP_LIKE, \@NE_Product);
    @State = ("Verified");
    $operator1->BuildFilter("State", $CQPerlExt::CQ_COMP_OP_EQ, \@State);

    my $resultSet = $session->BuildResultSet($queryDef);
    $resultSet->EnableRecordCount();
    $resultSet->Execute();
    my $count = $resultSet->GetRecordCount();#获取查询出的MR个数
    print "count: $count\n";
    ###遍历查询出的MR,并进行Close操作###
    while (($resultSet->MoveNext()) == 1)
    {
    $id = $resultSet->GetColumnValue(1);
    print "$id\n";
    ###执行Close操作###
    $entity = $session->GetEntity( "Dev_Defect", $id );
    $session->EditEntity($entity,"close");
    $entity->SetFieldValue("Closed_Information", "Close");
    my $Status = $entity->Validate();
    if($Status eq "")
    {
    # 提交数据记录
    $entity->Commit();
    }
    else
    {
    # 打印错误信息
    print $Status;
    $entity->Revert();
    }
    }
    CQSession::Unbuild($session);

    参考资料