高效的方法在Enterprise Architect中批量导入XMI

时间:2013-05-24 10:49:04

标签: optimization uml enterprise-architect xmi

我们的团队正在使用Enterprise Architect version 10SVN作为存储库。 由于EAP文件大小非常大(例如80 MB),我们会将每个包导出到单独的XMI中并将其存储到SVN中。 EAP文件本身是在一些里程碑之后提交的。问题是在开发过程中将EAP文件与co worker的工作同步,我们需要导入大量XMI(例如总数可以是500个文件)。

我知道一旦EAP文件更新,我们就可以使用Package Control - >获取最新消息。因此,只有在并行开发期间才会出现此问题。

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

  1. Ctrl + Alt + I (从XMI文件导入包)
  2. 选择要导入的文件名
  3. Alt + I (导入)
  4. 输入(是)
  5. 重复步骤2到4,直到模块完成
  6. 但是,导入数百个文件仍然效率低下。

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

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

2 个答案:

答案 0 :(得分:4)

EA中有一个scripting接口。您可以使用它自动导入。我没用过,但可能还不错。

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

<强> Multiworker

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

内置版本控制

其次,EA可以直接与SVN(和其他版本控制系统)交互。见this。简而言之,您可以设置EAP文件,以便单个程序包(以及它们下面的所有程序包)受SVN控制。然后,您可以查看单个软件包,进行编辑,重新检入。或者您确实可以查看软件包下方的整个分支(包括SVN控制的子软件包)。

引擎盖下EA正在导入和导出XMI文件并将其检入和检出SVN,而EAP文件始终是头版修订版。就像你手工做的那样,但是自动化。鉴于您可以使用单个EAP文件,这是有道理的。你必须要小心回滚 - 源自一个软件包的旧版本中的对象的链接可能指向不再存在的对象(但是你可以查看导入日志错误以查看是否是这种情况)。需要一点时间来适应,但它运作良好。

还有内置的软件包基线功能 - 无论如何都可能是您所需要的,并且非常有效,特别是如果您使用相同的EAP文件。

更大的数据库引擎

第三,您根本不必拥有EAP文件。模型的数据库可以在任何合适的数据库系统(MySQL,SQL Server,Oracle等)中。因此,它为您提供了各种选项,可以扩展其使用方式,通过WAN / Internet进行扩展等等。

简而言之,Sparx对EA如何在多工作环境中使用非常敏感,值得利用它。

答案 1 :(得分: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();