6

我们的团队正在使用Enterprise Architect version 10SVN用于存储库。因为EAP文件比较大(比如80MB),所以我们把每个包导出成单独XMI的,存到SVN. EAP文件本身在某个里程碑之后提交。EAP问题是在开发过程中将文件与同事的工作同步,我们需要导入很多XMI(例如总共可以是 500 个文件)。

我知道一旦EAP文件更新,我们可以使用 Package Control -> Get All Latest。因此,此问题仅在并行开发期间出现。

我们使用键盘快捷键进行导入,如下所示:

  1. Ctrl+ Alt+IXMI (从文件导入包)
  2. 选择要导入的文件名
  3. Alt+I(进口)
  4. Enter(是的)
  5. 重复步骤 2 到 4,直到模块完成

但是,导入数百个文件仍然是低效的。

我检查了控制包是否有批量导入/导出。当我明确硬编码时,批量导入/导出正在工作XMI Filename,但如果使用版本控制,则选项不可用(批量导入/导出选项为灰色)。

有没有更好的方法来同步EAPXMI文件?

4

2 回答 2

4

EA中有一个脚本接口。您也许可以使用它来自动导入。我没有用过它,但它可能相当不错。

我不确定我是否完全了解您的工作环境,但我有一些可能感兴趣的一般性观点。可能如果您以不同的方式使用 EA(尤其是我在下面的第一点),批量导入的需要可能会消失。

多工

首先,多人可以同时处理同一个 EAP 文件。EAP 文件只不过是一个 Access 数据库文件,EA 使用锁定来阻止多人同时编辑同一个包。但是您可以轻松地让多人同时在一个 EAP 文件中编辑不同的包。将 EAP 文件放在某个文件共享上是一种很好的方法。

内置修订控制

其次,EA 可以直接与 SVN(和其他版本控制系统)交互。看到这个。简而言之,您可以设置您的 EAP 文件,以便单个包(以及它们下面的所有内容)受 SVN 控制。然后,您可以签出单个包,对其进行编辑,重新签入。或者实际上您可以签出包下的整个分支(包括本身受 SVN 控制的子包)。

EA 的底层是导入和导出 XMI 文件,并将它们签入和签出 SVN,而 EAP 文件始终是主要版本。就像你手工做的一样,但是是自动化的。这是有道理的,因为您都可以使用一个 EAP 文件。您确实必须小心回滚 - 源自一个包的旧版本中的对象的链接可能指向不再存在的对象(但您可以查看导入日志错误以查看是否是这种情况)。这需要一点时间来适应,但效果很好。

还有内置的包基线功能 - 无论如何这可能就是您所需要的,并且工作得很好,特别是如果您都使用相同的 EAP 文件。

更大的数据库引擎

第三,您根本不需要 EAP 文件。该模型的数据库可以在任何合适的数据库系统(MySQL、SQL Server、Oracle 等)中。因此,这为您提供了各种选项来扩展其使用方式、在 WAN/Internet 上的情况等。

简而言之,Sparx 对于如何在多工人环境中使用 EA 非常明智,并且值得加以利用。

于 2013-06-01T06:58:31.703 回答
1

我已经使用 JScript 为自动化创建了 EA 脚本

这是执行导出的脚本:

!INC Local Scripts.EAConstants-JScript

/*
 * Script Name : Export List of SVN Packages
 * Author      : SDK
 * Purpose     : Export a package and all of its subpackages information related to version 
 *               controlled. The exported file then can be used to automatically import
 *               the XMIs
 * Date        : 30 July 2013
 * HOW TO USE  : 1. Select the package that you would like to export in the Project Browser
 *               2. Change the output filepath in this script if necessary.
 *                  By default it is "D:\\EAOutput.txt"
 *               3. Send the output file to your colleague who wanted to import the XMIs
 */

var f; 

function main()
{
    // UPDATE THE FOLLOWING OUTPUT FILE PATH IF NECESSARY
    var filename = "D:\\EAOutput.txt";

    var ForReading = 1, ForWriting = 2, ForAppending = 8;

    Repository.EnsureOutputVisible( "Script" );
    Repository.ClearOutput( "Script" );
    Session.Output("Start generating output...please wait...");

    var treeSelectedType = Repository.GetTreeSelectedItemType();

    switch ( treeSelectedType )
    {
        case otPackage:
        {
            var fso = new ActiveXObject("Scripting.FileSystemObject");
            f = fso.OpenTextFile(filename, ForWriting, true);

            var selectedObject as EA.Package;
            selectedObject = Repository.GetContextObject();
            reportPackage(selectedObject);
            loopChildPackages(selectedObject);

            f.Close();
            Session.Output( "Done! Check your output at " + filename);
            break;
        }
        default:
        {
            Session.Prompt( "This script does not support items of this type.", promptOK );
        }
    }
}

function loopChildPackages(thePackage)
{
    for (var j = 0 ; j < thePackage.Packages.Count; j++)
    {
        var child as EA.Package;
        child = thePackage.Packages.GetAt(j);
        reportPackage(child);
        loopChildPackages(child);
    }
}

function getParentPath(childPackage)
{
    if (childPackage.ParentID != 0)
    {
        var parentPackage as EA.Package;
        parentPackage =  Repository.GetPackageByID(childPackage.ParentID);
        return getParentPath(parentPackage) + "/" + parentPackage.Name;
    }
    return "";
}

function reportPackage(thePackage)
{
    f.WriteLine("GUID=" + thePackage.PackageGUID + ";"
                   + "NAME=" + thePackage.Name + ";" 
                   + "VCCFG=" + getVCCFG(thePackage) + ";" 
                   + "XML=" + thePackage.XMLPath + ";"
                   + "PARENT=" + getParentPath(thePackage).substring(1) + ";"
    );
}

function getVCCFG(thePackage)
{
    if (thePackage.IsVersionControlled)
    {
        var array = new Array();
        array = (thePackage.Flags).split(";");

        for (var z = 0 ; z < array.length; z++)
        {
            var pos = array[z].indexOf('=');

            if (pos > 0)
            {
                var key = array[z].substring(0, pos);
                var value = array[z].substring(pos + 1);

                if (key=="VCCFG")
                {
                    return (value);
                }
            }
        }
    }
    return "";
}

main();

以及执行导入的脚本:

!INC Local Scripts.EAConstants-JScript

/*
 * Script Name : Import List Of SVN Packages
 * Author      : SDK
 * Purpose     : Imports a package with all of its sub packages generated from 
 *               "Export List Of SVN Packages" script
 * Date        : 01 Aug 2013
 * HOW TO USE  : 1. Get the output file generated by "Export List Of SVN Packages" script
 *                  from your colleague
 *               2. Get the XMIs in the SVN local copy
 *               3. Change the path to the output file in this script if necessary (var filename).
 *                  By default it is "D:\\EAOutput.txt"
 *               4. Change the path to local SVN
 *               5. Run the script
 */

var f; 
var svnPath;

function main()
{
    // CHANGE THE FOLLOWING TWO LINES ACCORDING TO YOUR INPUT AND LOCAL SVN COPY
    var filename = "D:\\EAOutput.txt";
    svnPath = "D:\\svn.xxx.com\\yyy\\docs\\design\\";

    var ForReading = 1, ForWriting = 2, ForAppending = 8;

    Repository.EnsureOutputVisible( "Script" );
    Repository.ClearOutput( "Script" );
    Session.Output("[INFO] Start importing packages from " + filename + ". Please wait...");

    var fso = new ActiveXObject("Scripting.FileSystemObject");
    f = fso.OpenTextFile(filename, ForReading);

    // Read from the file and display the results.
    while (!f.AtEndOfStream)
    {
        var r = f.ReadLine();
        parseLine(r);
        Session.Output("--------------------------------------------------------------------------------");
    }

    f.Close();
    Session.Output("[INFO] Finished");
}

function parseLine(line)
{
    Session.Output("[INFO] Parsing " + line);

    var array = new Array();
    array = (line).split(";");

    var guid;
    var name;
    var isVersionControlled;
    var xmlPath;
    var parentPath;

    isVersionControlled = false;
    xmlPath = "";

    for (var z = 0 ; z < array.length; z++)
    {
        var pos = array[z].indexOf('=');

        if (pos > 0)
        {
            var key = array[z].substring(0, pos);
            var value = array[z].substring(pos + 1);

            if (key=="GUID") {
                guid = value;
            } else if (key=="NAME") {
                name = value;
            } else if (key=="VCCFG") {
                if (value != "") {
                    isVersionControlled = true;
                }
            } else if (key=="XML") {
                if (isVersionControlled) {
                    xmlPath = value;
                }
            } else if (key=="PARENT") {
                parentPath = value;
            }
        }
    }

    // Quick check for target if already exist to speed up process
    var targetPackage as EA.Package;
    targetPackage = Repository.GetPackageByGuid(guid);
    if (targetPackage != null)
    {
        // target exists, do not do anything
        Session.Output("[DEBUG] Target package \"" + name + "\" already exist");
        return;
    }

    var paths = new Array();
    var packages = new Array(paths.Count);

    for (var i = 0; i < paths.Count; i++)
    {
        packages[i] = null;
    }

    paths = (parentPath).split("/");

    if (paths.Count < 2)
    {
        Session.Output("[INFO] Skipped root or level1");
        return;
    }

    packages[0] = selectRoot(paths[0]);
    packages[1] = selectPackage(packages[0], paths[1]);

    if (packages[1] == null)
    {
        Session.Output("[ERROR] Cannot find " + paths[0] + "/" + paths[1] + "in Project Browser");
        return;
    }

    for (var j = 2; j < paths.length; j++)
    {
        packages[j] = selectPackage(packages[j - 1], paths[j]);
        if (packages[j] == null)
        {
            Session.Output("[DEBUG] Creating " + packages[j].Name);

            // create the parent package
            var parent as EA.Package;
            parent = Repository.GetPackageByGuid(packages[j-1].PackageGUID);
            packages[j] = parent.Packages.AddNew(paths[j], "");
            packages[j].Update();
            parent.Update();
            parent.Packages.Refresh();
            break;
        }
    }

    // Check if name (package to import) already exist or not
    var targetPackage = selectPackage(packages[paths.length - 1], name);

    if (targetPackage == null)
    {
        if (xmlPath == "")
        {
            Session.Output("[DEBUG] Creating " + name);

            // The package is not SVN controlled
            var newPackage as EA.Package;
            newPackage = packages[paths.length - 1].Packages.AddNew(name,"");
            Session.Output("New GUID = " + newPackage.PackageGUID);
            newPackage.Update();
            packages[paths.length - 1].Update();
            packages[paths.length - 1].Packages.Refresh();
        }
        else
        {
            // The package is not SVN controlled
            Session.Output("[DEBUG] Need to import: " + svnPath + xmlPath);

            var project as EA.Project;
            project = Repository.GetProjectInterface;
            var result;

            Session.Output("GUID = " + packages[paths.length - 1].PackageGUID);
            Session.Output("GUID XML = " + project.GUIDtoXML(packages[paths.length - 1].PackageGUID));
            Session.Output("XMI file = " + svnPath + xmlPath);
            result = project.ImportPackageXMI(project.GUIDtoXML(packages[paths.length - 1].PackageGUID), svnPath + xmlPath, 1, 0);
            Session.Output(result);

            packages[paths.length - 1].Update();
            packages[paths.length - 1].Packages.Refresh();
        }

    }
    else
    {
        // target exists, do not do anything
        Session.Output("[DEBUG] Target package \"" + name + "\" already exist");
    }
}

function selectPackage(thePackage, childName)
{
    var childPackage as EA.Package;
    childPackage = null;

    if (thePackage == null)
        return null;

    for (var i = 0; i < thePackage.Packages.Count; i++)
    {
        childPackage = thePackage.Packages.GetAt(i);

        if (childPackage.Name == childName)
        {
            Session.Output("[DEBUG] Found " + childName);
            return childPackage;
        }
    }

    Session.Output("[DEBUG] Cannot find " + childName);
    return null;
}

function selectRoot(rootName)
{
    for (var y = 0; y < Repository.Models.Count; y++)
    {
        root = Repository.Models.GetAt(y);
        if (root.Name == rootName)
        {
            return root;
        }
    }
    return null;
}

main();
于 2013-08-01T07:53:20.543 回答