Sparx Systems Forum

Enterprise Architect => Automation Interface, Add-Ins and Tools => Topic started by: SteveC on September 13, 2018, 02:17:26 am

Title: SOLVED:Retrieve All Elements On A Diagram
Post by: SteveC on September 13, 2018, 02:17:26 am
We are looking for a way to get a list of elements on the current diagram. This can be using code or SQL query.

It looks like using the DiagramObjects property on the Diagram class might be the way to go, but it is not clear how one might get the elements from this collection. Similarly, t_diagramobjects seems to be the table to query, but it's not clear how to parse element references from it.

Thanks in advance for any guidance!
Title: Re: Retrieve All Elements On A Diagram
Post by: EXploringEA on September 13, 2018, 02:26:31 am
Yes - uses the diagram.diagramobjects then for each of the diagramobjects use the ElementID to access the element object and its properties
Title: Retrieve All Elements On A Diagram
Post by: SteveC on September 13, 2018, 03:10:54 am
It is a simple as:
Code: [Select]
foreach (EA.DiagramObject diagramObject in diagram.DiagramObjects) {
    EA.Element element = Repository.GetElementByID(diagramObject.ElementID);
    // work with the element here
}

Thanks!
Title: Re: SOLVED:Retrieve All Elements On A Diagram
Post by: priombiswas89 on December 11, 2020, 09:52:07 pm
Is there a way to find the diagram by package and then list all the elements of the diagram? I am trying to do that in c#
Title: Re: SOLVED:Retrieve All Elements On A Diagram
Post by: Uffe on December 11, 2020, 09:58:48 pm
Is there a way to find the diagram by package and then list all the elements of the diagram? I am trying to do that in c#

There is no "the" diagram relating to a package, but the Package class has a .Diagrams collection which you can loop through to find the diagram you want, and then iterate over that Diagram's .DiagramObjects to retrieve the elements shown on the diagram.

HTH,


/Uffe
Title: Re: SOLVED:Retrieve All Elements On A Diagram
Post by: qwerty on December 11, 2020, 10:28:25 pm
There's the composite diagram for an element which you can call THE diagram. Objects with t_object.NType == 8 have a composite diagram which can be found via that dreaded t_xref.

q.
Title: Re: SOLVED:Retrieve All Elements On A Diagram
Post by: Geert Bellekens on December 11, 2020, 10:43:19 pm
Packages are even funnier. You don't need to set a composite diagram in order to navigate to the diagram on double-click.
EA simply opens the first diagram under the package it finds when double-clicking on a package in a diagram.

Geert
Title: Re: SOLVED:Retrieve All Elements On A Diagram
Post by: qwerty on December 11, 2020, 11:17:11 pm
Yeah. We got so used to EAUI... For composite elements you can choose an arbitrary diagram. But for packages it's always that first diagram.

q.
Title: Re: SOLVED:Retrieve All Elements On A Diagram
Post by: Uffe on December 11, 2020, 11:24:29 pm
Not only that, but two elements can share the same target diagram, while two packages cannot.

/U
Title: Re: SOLVED:Retrieve All Elements On A Diagram
Post by: Paolo F Cantoni on December 12, 2020, 10:24:19 am
Not only that, but two elements can share the same target diagram, while two packages cannot.

/U
Yeah,  We had all sort of issues with our automatic diagrammer until we realised that two different elements were pointing tot he same diagram!

Just because you can, doesn't mean you should...  ;D

Paolo
Title: Re: SOLVED:Retrieve All Elements On A Diagram
Post by: priombiswas89 on December 13, 2020, 07:47:13 am
Is there a way to find the diagram by package and then list all the elements of the diagram? I am trying to do that in c#

There is no "the" diagram relating to a package, but the Package class has a .Diagrams collection which you can loop through to find the diagram you want, and then iterate over that Diagram's .DiagramObjects to retrieve the elements shown on the diagram.

HTH,


/Uffe

I have tried the below code so far:

Code: [Select]
                EA.Collection packages = Rep.Models;
                for (short ip = 0; ip < packages.Count; ip++)
                {
                    EA.Package child = (EA.Package)packages.GetAt(ip);
                   
                    foreach (EA.Diagram theDiagram in child.Diagrams)
                    {
                        foreach (EA.DiagramObject theDiagramObject in theDiagram.DiagramObjects)
                        {
                            Console.WriteLine(theDiagramObject.ElementID);
                        }[img]
https://ibb.co/2KxDtXH
[/img]
I have included the image link here. So far, I am getting the package but not getting anything on [b]child.Diagrams[/b]. Am I missing something?
                    }
                }
Title: Re: SOLVED:Retrieve All Elements On A Diagram
Post by: Uffe on December 13, 2020, 10:07:18 pm
Hi again,

Yes. You're not traversing the package structure properly.
child is actually the "Models" root node, not the "StateMachineDiagram1" view.

/Uffe
Title: Re: SOLVED:Retrieve All Elements On A Diagram
Post by: Geert Bellekens on December 13, 2020, 10:39:52 pm
If you call the same function recursively for all sub-packages if you can traverse the whole model.
But be aware that this will be very time consuming in a "real" model.

You might want to think about how to restrict it to what you really need.

You can either do that by letting the user select a package, or diagram and starting from there, or use an SQL Query to get only the elements or packages you need.

Geert

PS. Usually a State Machine diagram is not owned by a package directly, but by a State Machine element. In that case you'll have to iterate the EA.Element.Diagrams collection because it will not be in the EA.Package.Diagrams collection.
Title: Re: SOLVED:Retrieve All Elements On A Diagram
Post by: priombiswas89 on December 14, 2020, 10:15:52 pm
Thanks for your suggestion. It indeed lies inside Element.Diagrams, not inside Package.Diagrams. I have tried the below code:
Code: [Select]
EA.Collection models = Rep.Models;
                for (short i1 = 0; i1 < models.Count; i1++)
                {
                    EA.Package childModel = (EA.Package)models.GetAt(i1);
                    EA.Collection packages = childModel.Packages;

                    for (short i2 = 0; i2 < packages.Count; i2++)
                    {
                        EA.Package childPackage = (EA.Package)packages.GetAt(i2);
                        EA.Collection elements = childPackage.Elements;
                        foreach (EA.Element element in elements)
                        {
                            packageNames.Add($"{element.Type} : {element.Name}");

                            foreach (EA.Connector item in element.Connectors)
                            {
                                packageNames.Add($"Trigger: {item.TransitionEvent} \n Effect: {item.TransitionAction}");
                                //packageNames.Add(item.ClientEnd.);
                            }
                        }
                    }

What I am now trying to achieve is a JSON or XML representation of the state machine like the below structure:

Code: [Select]
states:
- name: Off
- name: Boot
- name: uPError
transitions:
- from: Off
  to: Boot
  trigger: register
  effects: [switch on uP]
- from: Boot
  to: Wait for HK
  trigger: after(1s)
  effects: [start HK]

and later convert it to YAML file. I am trying to traverse inside the diagram to find the connection, but still hasn't got to find the from and to state machine reference. Although I can see a property Start Point X and End Point X in connector, it doesn't contain any information about the from or to which state machine it's coming or going.
Title: Re: SOLVED:Retrieve All Elements On A Diagram
Post by: Geert Bellekens on December 14, 2020, 10:53:47 pm
To and from elements are referenced using the ClientID (From) and SupplierID (To) of the connector.

Use Repository.GetElementByID() get get to the other end.

For a correct model you should indeed not need the diagram at all to be able to parse the whole statemachine like you are doing now.
Just be aware that quite often "orphaned" elements remain in the project browser.

Geert
Title: Re: SOLVED:Retrieve All Elements On A Diagram
Post by: priombiswas89 on December 15, 2020, 12:57:36 am
Are you talking about selecting specific element or package, for example using the below documentation?

https://sparxsystems.com/enterprise_architect_user_guide/13.0/automation/objecttypeenum.html (https://sparxsystems.com/enterprise_architect_user_guide/13.0/automation/objecttypeenum.html)
Title: Re: SOLVED:Retrieve All Elements On A Diagram
Post by: Geert Bellekens on December 15, 2020, 01:02:37 am
Are you talking about selecting specific element or package, for example using the below documentation?

https://sparxsystems.com/enterprise_architect_user_guide/13.0/automation/objecttypeenum.html (https://sparxsystems.com/enterprise_architect_user_guide/13.0/automation/objecttypeenum.html)
Yes, indeed.
That is a way to allow the user to select where to start.
If you are making an add-in you can add a context menu option to start your functionality.

Another option would be use to use the construct picker to let the user select an element.

Geert
Title: Re: SOLVED:Retrieve All Elements On A Diagram
Post by: priombiswas89 on December 15, 2020, 05:32:10 am
Are you talking about selecting specific element or package, for example using the below documentation?

https://sparxsystems.com/enterprise_architect_user_guide/13.0/automation/objecttypeenum.html (https://sparxsystems.com/enterprise_architect_user_guide/13.0/automation/objecttypeenum.html)
Yes, indeed.
That is a way to allow the user to select where to start.
If you are making an add-in you can add a context menu option to start your functionality.

Another option would be use to use the construct picker to let the user select an element.

Geert

It is working with the following code, so far the package and element is working fine, except the diagram, I am trying to find a way to navigate to elements of diagram but so far haven't been succeeded:

Code: [Select]
                EA.Package pack;
                EA.Diagram diag;
                EA.Element ele;
                switch (Rep.GetContextItemType())
                {
                    case EA.ObjectType.otPackage:
                        {
                            pack = Rep.GetContextObject();
                            EA.Collection elements = pack.Elements;
                            foreach (EA.Element element in elements)
                            {
                                if (element.Type != "Trigger")
                                {
                                    packageNames.Add($"{element.Type} : {element.Name}");
                                }
                                foreach (EA.Connector item in element.Connectors)
                                {
                                    int clientId = item.ClientID;
                                    int supplierId = item.SupplierID;
                                    EA.Element clientElement = Rep.GetElementByID(clientId);
                                    EA.Element supplierElement = Rep.GetElementByID(supplierId);

                                    packageNames.Add($" From : {clientElement.Name}\n To: {supplierElement.Name}\n Trigger: {item.TransitionEvent}\n Effect: {item.TransitionAction}");
                                }
                            }
                            break;
                        }
                    case EA.ObjectType.otDiagram:
                        {
                            diag = Rep.GetContextObject();
                            foreach (EA.Element element in diag.DiagramObjects)
                            {
                                if (element.Type != "Trigger")
                                {
                                    packageNames.Add($"{element.Type} : {element.Name}");
                                }
                                foreach (EA.Connector item in element.Connectors)
                                {
                                    int clientId = item.ClientID;
                                    int supplierId = item.SupplierID;
                                    EA.Element clientElement = Rep.GetElementByID(clientId);
                                    EA.Element supplierElement = Rep.GetElementByID(supplierId);

                                    packageNames.Add($" From : {clientElement.Name}\n To: {supplierElement.Name}\n Trigger: {item.TransitionEvent}\n Effect: {item.TransitionAction}");
                                }
                            }
                            break;
                        }
                    case EA.ObjectType.otElement:
                        {
                            ele = Rep.GetContextObject();
                            packageNames.Add($"{ele.Type} : {ele.Name}");
                            foreach (EA.Connector item in ele.Connectors)
                            {
                                int clientId = item.ClientID;
                                int supplierId = item.SupplierID;
                                EA.Element clientElement = Rep.GetElementByID(clientId);
                                EA.Element supplierElement = Rep.GetElementByID(supplierId);

                                packageNames.Add($" From : {clientElement.Name}\n To: {supplierElement.Name}\n Trigger: {item.TransitionEvent}\n Effect: {item.TransitionAction}");
                            }
                            break;
                        }
                }
Title: Re: SOLVED:Retrieve All Elements On A Diagram
Post by: Geert Bellekens on December 15, 2020, 06:05:55 am
Code: [Select]
foreach (EA.Element element in diag.DiagramObjects)This is where you are going wrong. There are no EA.Elements in the DiagramObjects collection, only EA.DiagramObjects (yes, sometimes it's that obvious, certainly not always though ;D)
Try
Code: [Select]
foreach (EA.DiagramObject diagramObject in diag.DiagramObjects)
Geert