Book a Demo

Author Topic: reading variables  (Read 6819 times)

tm200014

  • EA Novice
  • *
  • Posts: 12
  • Karma: +0/-0
    • View Profile
reading variables
« on: September 22, 2010, 04:24:34 pm »
Hello,

I have an Enterprise Architect project which includes many functions, variables, structs and enumerations. I would like to read those programatically in C# and generate code.

I can't find out where the variables and functions are located though. Can anyone help me out?

I tried (just as it sais in the help) walking through all the elements. I can't find the variables though...

here is my code so far:

Code: [Select]
   public partial class Form1 : Form
    {
        EA.Repository r;
        List<string> list;
        List<string> elementsList;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            list = new List<string>();
            elementsList = new List<string>();
            r = new EA.Repository();
            r.OpenFile(@"D:\EA\08-1A3811-002_SWA.EAP");
        }

        private void button2_Click(object sender, EventArgs e)
        {
            list = new List<string>();
            elementsList = new List<string>();
            for (int i = 0; i < r.Models.Count; i++)
            {
                DumpPackage((EA.Package)r.Models.GetAt((short)i));
            }
        }

        private void DumpPackage(EA.Package package)
        {
            list.Add("Package Name: " + package.Name);
            listBox1.Items.Add("Package Name: " + package.Name);
            treeView1.Nodes.Add(package.Name);
            DumpElements(package);
            for (int i = 0; i < package.Packages.Count; i++)
            {
                DumpPackage((EA.Package)package.Packages.GetAt((short)i));
            }
        }

        private void DumpElements(EA.Package package)
        {
            for (int i = 0; i < package.Elements.Count; i++)
            {
                elementsList.Add(((EA.Element)package.Elements.GetAt((short)i)).Name);
                listBox1.Items.Add("Element: " + ((EA.Element)package.Elements.GetAt((short)i)).Name + ((EA.Element)package.Elements.GetAt((short)i)).Elements.Count);
                int index = treeView1.Nodes.Count - 1;
                treeView1.Nodes[index].Nodes.Add(((EA.Element)package.Elements.GetAt((short)i)).Name);
                //MessageBox.Show(((EA.Element)package.Elements.GetAt((short)i)).Name);
            }
        }
}
« Last Edit: September 22, 2010, 04:25:27 pm by tm200014 »

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: reading variables
« Reply #1 on: September 22, 2010, 04:38:36 pm »
What do you mean by variables? I don't know such a UML construct.

When trying to interprete the code you posted I see that you are traversing packages and elements.
I can imagine you would want to traverse the elements attributes and operations as well?

Geert

tm200014

  • EA Novice
  • *
  • Posts: 12
  • Karma: +0/-0
    • View Profile
Re: reading variables
« Reply #2 on: September 22, 2010, 05:15:56 pm »
Sorry... I just realized that I didn't make myself clear :)

In the EA project, we defined variables and functions of our code. These are (as far as i know) called attributes and operations. So this is what i want to read!
« Last Edit: September 22, 2010, 05:16:37 pm by tm200014 »

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: reading variables
« Reply #3 on: September 22, 2010, 05:25:37 pm »
Ok, then you'll need to traverse Element.Attributes and Element.Methods (for the operations -> functions)

Geert

tm200014

  • EA Novice
  • *
  • Posts: 12
  • Karma: +0/-0
    • View Profile
Re: reading variables
« Reply #4 on: September 22, 2010, 05:28:20 pm »
thanks! thats what i thought after your last post...

is there a tutorial for this? because i cant seem to get it working!

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: reading variables
« Reply #5 on: September 22, 2010, 05:43:19 pm »
What's exactly the problem?
You'll just have to create a DumpAttributes(Element) and DumpOperations(Elements) much in the same way as your DumpElements operation.

Geert

tm200014

  • EA Novice
  • *
  • Posts: 12
  • Karma: +0/-0
    • View Profile
Re: reading variables
« Reply #6 on: September 22, 2010, 05:57:28 pm »
I just got it to work for attributes. Thanks for your help!!!. I loaded the wrong file which is VERY VERY big and takes a long time. I will try do parse functions now.

Is it normal that the communication between the .NET program and EA is so slow? I need about 2 minutes just to open the connection to the server.

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: reading variables
« Reply #7 on: September 22, 2010, 06:07:10 pm »
Yes, expect it to be slow, especially if you are recusively traversing the whole model.
I don't know what exactly the purpose if of your program, but if you only want to display some information about the model, without the need to change anything, you might want to consider alternative ways.

For a recent project I needed to dump all elements and attributes (owned by the selected package recursively) to an excel file.
I first started out with a classical visitor, but that took about three hours to run on a package with about 10.000 elements.
Since that wasn't really usable I used the Repository.SQLQuery to get the information I needed.
Runtime went from 3 hours to 3 seconds, including the time to create and save the excel file. :o

Geert

tm200014

  • EA Novice
  • *
  • Posts: 12
  • Karma: +0/-0
    • View Profile
Re: reading variables
« Reply #8 on: September 22, 2010, 06:23:13 pm »
That would be very good for me because I don't need to change anything either. I only have to get all attributes and operations.

Is it possible for you to post some of your code as an example? I don't really know much about SQL queries... Only the basics!

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: reading variables
« Reply #9 on: September 22, 2010, 06:55:39 pm »
Code looks like this. This works for a repository on SQL Server, so you might need to tweak the SQL to comply with MSAccess's version of the SQL syntax.
For some reason SQLQuery operation doesn't like recursive queries so I had to include "enough" levels of nesting.

In my EA.Package wrapper:
Code: [Select]
/// <summary>
        /// returns an xml document with a flat list of the owned elements modified after the given date
        /// </summary>
        /// <param name="modifiedAfter">the date after wich the elements should be modified</param>
        /// <returns>the owned elements in xml format</returns>
        public XmlDocument exportOwnedElements(DateTime modifiedAfter)
        {
            string sqlDateModified = modifiedAfter.ToString("yyyy-MM-dd");
            string sqlQuery =
                " SELECT o.Object_ID as ID,o.Object_Type as Type,isNull(o.Name,'') as Name,ISNULL(t.value,0) as ImportanceLevel,isnull(o.Author,'') as Author,o.CreatedDate as Created,o.ModifiedDate as Modified,isnull(o.Note,'') as Documentation,isnull(o.Package_ID,'') as ParentID,isnull(p.name,'') as ParentName  " +
                " ,isnull(p9.Name +'.','') + isnull(p8.Name+'.','')+ isnull(p7.Name+'.','')+ isnull(p6.Name+'.','') " +
                " + isnull(p5.Name+'.','')+ isnull(p4.Name+'.','')+ isnull(p3.Name+'.','')+ isnull(p2.Name+'.','')+ isnull(p.Name,'') as QualifiedName " +
                " FROM ((((((((((t_object as o  " +
                " left join t_objectproperties t on t.Object_ID = o.Object_ID )" +
                " left join t_package p on o.Package_ID = p.Package_ID )" +
                " left join t_package p2 on p.Parent_ID = p2.Package_ID )" +
                " left join t_package p3 on p2.Parent_ID = p3.Package_ID )" +
                " left join t_package p4 on p3.Parent_ID = p4.Package_ID )" +
                " left join t_package p5 on p4.Parent_ID = p5.Package_ID )" +
                " left join t_package p6 on p5.Parent_ID = p6.Package_ID )" +
                " left join t_package p7 on p6.Parent_ID = p7.Package_ID )" +
                " left join t_package p8 on p7.Parent_ID = p8.Package_ID )" +
                " left join t_package p9 on p8.Parent_ID = p9.Package_ID )" +

                " where (t.Property = 'ImportanceLevel' or t.Property is null)" +
                " and o.ModifiedDate > '" + sqlDateModified + "' " +
                " and (p.package_ID = " + this.getPackageID() + "  " +
                    " or p2.package_ID = " + this.getPackageID() + "  " +
                    " or p3.package_ID = " + this.getPackageID() + "  " +
                    " or p4.package_ID = " + this.getPackageID() + "  " +
                    " or p5.package_ID = " + this.getPackageID() + "  " +
                    " or p6.package_ID = " + this.getPackageID() + "  " +
                    " or p7.package_ID = " + this.getPackageID() + "  " +
                    " or p8.package_ID = " + this.getPackageID() + "  " +
                    " or p9.package_ID = " + this.getPackageID() + " ) " +
                " order by QualifiedName";
            return ((EAModel)this.model).SQLQuery(sqlQuery);

        }
I use this operation in my excel exporter:
Code: [Select]
       /// <summary>
        /// actually export the data
        /// </summary>
        /// <param name="sourcePackage">the source package</param>
        /// <param name="modifiedFilterDate">the data after which the elements are changed</param>
        protected void exportData(ACVPackage sourcePackage, DateTime modifiedFilterDate)
        {
            Logger.log("starting export");
            XmlDocument xmlElements = sourcePackage.exportOwnedElements(modifiedFilterDate);
            //convert xml document to object array
            object[,] marshalledElements = this.MarshalXmlDocumentToArray(xmlElements);
            //write to output file
            this.write(marshalledElements);
            Logger.log("finished export");
        }

end of part 1... to be continued

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: reading variables
« Reply #10 on: September 22, 2010, 06:57:35 pm »
Then I convert the xml to an object array
Code: [Select]
/// <summary>
        /// converts the given xml document to a two dimensional array of strings
        /// </summary>
        /// <param name="xmlElements">the xml document containing the information about the elements</param>
        /// <returns>the converted two dimensional array of strings</returns>
        protected object[,] MarshalXmlDocumentToArray(XmlDocument xmlElements)
        {


            object[,] marshalledElements;
            //first check if there is data to be imported
            if (xmlElements.SelectSingleNode("//Row") != null)
            {
                //convert to XDocument for better performance
                XDocument xElements = XDocument.Load(xmlElements.CreateNavigator().ReadSubtree());

                var query = from xElem in xElements.Element("EADATA").Element("Dataset_0").Element("Data").Elements("Row")
                            select new ExportRow
                            {
                                ID = xElem.Element("ID").Value,
                                Type = xElem.Element("Type").Value,
                                Name = xElem.Element("Name").Value,
                                ImportanceLevel = xElem.Element("ImportanceLevel").Value,
                                Author = xElem.Element("Author").Value,
                                Created = xElem.Element("Created").Value,
                                Modified = xElem.Element("Modified").Value,
                                Documentation = xElem.Element("Documentation").Value,
                                ParentName = xElem.Element("ParentName").Value,
                                ParentID = xElem.Element("ParentID").Value,
                                QualifiedName = xElem.Element("QualifiedName").Value
                            };
                //query
                List<ExportRow> rows = query.ToList();

                //first add the headers
                marshalledElements = new object[rows.Count, 11];
                //headers now in the template excel file
                //marshalledElements = this.addHeaders(marshalledElements);
                //then add all rows
                for (int i = 0; i < rows.Count; i++)
                {
                    ExportRow row = rows[i];
                    marshalledElements[i , 0] = rows[i].ID;
                    marshalledElements[i , 1] = rows[i].Type;
                    marshalledElements[i , 2] = rows[i].Name;
                    marshalledElements[i , 3] = rows[i].ImportanceLevel;
                    marshalledElements[i , 4] = rows[i].Author;
                    DateTime createdDate;
                    if (DateTime.TryParse(rows[i].Created, out createdDate))
                    {
                        marshalledElements[i , 5] = createdDate;
                    }
                    else
                    {
                        //if the date cannot be parsed then just add the string as is
                        marshalledElements[i , 5] = rows[i].Created;
                    }
                    DateTime modifiedDate;
                    if (DateTime.TryParse(rows[i].Modified, out modifiedDate))
                    {
                        marshalledElements[i , 6] = modifiedDate;
                    }
                    else
                    {
                        //if the date cannot be parsed then just add the string as is
                        marshalledElements[i , 6] = rows[i].Modified;
                    }
                    marshalledElements[i , 7] = rows[i].QualifiedName;
                    if (rows[i].Documentation.Length < 255)
                    {
                        marshalledElements[i , 8] = rows[i].Documentation;
                    }
                    else
                    {
                        marshalledElements[i , 8] = rows[i].Documentation.Substring(0, 254);
                    }
                    marshalledElements[i , 9] = rows[i].ParentName;
                    marshalledElements[i , 10] = rows[i].ParentID;
                }

            }
            else
            {
                //no data, just returns the array with the headers
                marshalledElements = new string[1, 11];
                //marshalledElements = this.addHeaders(marshalledElements);
            }
            return marshalledElements;
        }

This object array is then passed onto the write function that will actually create the excel file

end of part2... to be continued

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: reading variables
« Reply #11 on: September 22, 2010, 06:59:18 pm »
Code: [Select]
/// <summary>
        /// writes the details of the marshalled elements to the excel file
        /// </summary>
        /// <param name="marshalledElements">the marshalled elements</param>
        protected override void write(object[,] marshalledElements)
        {

            if (excel == null)
            {
                //open Excel file
                if (this.templateRootPath == null)
                {
                    this.templateRootPath = new System.Uri(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase));
                }
                excel = new ExcelConnector(System.IO.Path.Combine(this.templateRootPath.LocalPath, @".\Files\EA_Export.xltm"), true);
            }
            //no headers so start writing at row 2
            excel.write(marshalledElements,2);
            //figure out which columns contain dates. those columns should be formatted as dates.
            for (int i = 0; i < marshalledElements.GetUpperBound(1); i++)
            {
                if (marshalledElements.GetUpperBound(0)> 1 && marshalledElements[0, i] is DateTime)
                {
                    excel.FormatColumnAsDate(i);
                }
            }
            if (!refresh)
            {
                excel.autofitColumns();
                excel.freezePanes();
                excel.setVariable("sourceID", this.source.getID());
                excel.Save(this.excelFilePath);
                excel.close();
            }
        }

excel.write looks lik this:
Code: [Select]
       /// <summary>
        /// write the contents to the excel sheet starting at the given row
        /// </summary>
        /// <param name="contents">the context to write</param>
        /// <param name="beginrow">the row to start from</param>
        public void write(object[,] contents, int beginrow)
        {
            //get the exact range where the contents should be placed
            Range targetRange = sheet.get_Range(sheet.Cells[beginrow, 1], sheet.Cells[contents.GetUpperBound(0)+1 + beginrow-1, contents.GetUpperBound(1)+1]);
            targetRange.Value2 = contents;
        }

I hope this helps.

Geert

tm200014

  • EA Novice
  • *
  • Posts: 12
  • Karma: +0/-0
    • View Profile
Re: reading variables
« Reply #12 on: September 22, 2010, 07:00:22 pm »
Ok! Thank you very much!

I will give it a try!