Author Topic: Retrieve nested elements from an element and display name with parent name  (Read 7455 times)

priombiswas89

  • EA User
  • **
  • Posts: 47
  • Karma: +0/-0
    • View Profile
I am trying to retrieve the embedded/nested elements from an element and display the names of embedded elements with parent element.
Below is the image of my model:

https://ibb.co/XyHT8z7

The format I want to  achieve for list of the states are as follows:


off
Boot
Wait for HK
uPError
Run/AliveQuery
Run/AliveQuery/State1
Run/WaitAliveResponse
Run/WaitAliveResponse/State2
Run/WaitAliveResponse/State2/State3


The code so far I have tried is as follows:

Code: [Select]
case EA.ObjectType.otDiagram:
                        {
                            diag = Rep.GetContextObject();

                            diagramElementsObj.refDiagramId = diag.DiagramGUID;
                            diagramElementsObj.refDiagramName = diag.Name;

                            diagramElementsObj.states = new List<State>();
                            diagramElementsObj.transitions = new HashSet<Transition>();

                            foreach (EA.DiagramObject diagramObj in diag.DiagramObjects)
                            {
                                int diagramId = diagramObj.DiagramID;
                                EA.Diagram diagram = Rep.GetDiagramByID(diagramId);

                                int elementId = diagramObj.ElementID;
                                EA.Element element = Rep.GetElementByID(elementId);

                                #region For object creation

                                if (!string.IsNullOrEmpty(element.Name))
                                {
                                    if (element.Type.Contains("StateNode"))
                                    {
                                        diagramElementsObj.initialState = element.Name;
                                    }
                                    else
                                    {
                                        State stateObj = new State();
                                        stateObj.name = element.Name;
                                        stateObj.operations = new List<Operation>();
                                        diagramElementsObj.states.Add(stateObj);

                                        // To get embedded elements
                                        if (element.Elements.Count > 0)
                                        {
                                            for (short ip = 0; ip < element.Elements.Count; ip++)
                                            {
                                                int parentId = 0;
                                                EA.Element child = (EA.Element)element.Elements.GetAt(ip);
                                                parentId = child.ParentID;
                                                EA.Element parent = Rep.GetElementByID(parentId);
                                                stateObj.name = $"{parent.Name}/{child.Name}";
                                                GetEmbeddedElement(child);
                                            }
                                        }

                                        if (element.Methods.Count > 0)
                                        {
                                            // To get embedded operations and their corresponding action type, eg. entry, exit, do for state diagram
                                            foreach (EA.Method meth in element.Methods)
                                            {
                                                Operation operationObj = new Operation();
                                                operationObj.name = meth.Name;
                                                operationObj.type = meth.ReturnType;
                                                stateObj.operations.Add(operationObj);
                                            }
                                        }
                                    }
                                }
                                #endregion

                                foreach (EA.Connector item in element.Connectors)
                                {
                                    bool isOld = false;
                                    int clientId = item.ClientID;
                                    int supplierId = item.SupplierID;
                                    EA.Element clientElement = Rep.GetElementByID(clientId);
                                    EA.Element supplierElement = Rep.GetElementByID(supplierId);

                                    #region For object creation
                                    Transition transitionObj = new Transition();
                                    transitionObj.from = clientElement.Name;
                                    transitionObj.to = supplierElement.Name;
                                    transitionObj.trigger = item.TransitionEvent;
                                    string effectsList = item.TransitionAction;
                                    effectsList = effectsList.ReplaceAll(charsToReplace, ',');
                                    effectsList = Utilities.TruncateCommas(effectsList);
                                    transitionObj.effects = $"[{effectsList}]";

                                    foreach (var transItem in diagramElementsObj.transitions)
                                    {
                                        if (transItem.from.Equals(transitionObj.from) && transItem.to.Equals(transitionObj.to))
                                        {
                                            isOld = true;
                                            break;
                                        }
                                    }
                                    if (!isOld)
                                    {
                                        diagramElementsObj.transitions.Add(transitionObj);
                                    }
                                    #endregion

                                }
                            }

                            break;
                        }


Below is the recursive method:

Code: [Select]

private void GetEmbeddedElement(EA.Element element)
        {
            EA.Collection elements = element.Elements;
            for (short ip = 0; ip < elements.Count; ip++)
            {
                EA.Element child = (EA.Element)elements.GetAt(ip);
                GetEmbeddedElement(child);
            }
        }


The output I am getting as follows:


off
Boot
Wait for HK
uPError
Run/WaitAliveResponse
AliveQuery/State1
WaitAliveResponse/State2


Any kind of help will be much appreciated.



« Last Edit: January 08, 2021, 01:09:10 am by priombiswas89 »

qwerty

  • EA Guru
  • *****
  • Posts: 13584
  • Karma: +396/-301
  • I'm no guru at all
    • View Profile
No proof reading your code, but embedded has different meanings. You seem to expect that diagram embedded is the same as element embedded. That's not the case. On a diagram you can graphically embed anything. So maybe you are mislead by the graphics. Look into the browser to see the real element embedding.

q.

priombiswas89

  • EA User
  • **
  • Posts: 47
  • Karma: +0/-0
    • View Profile
Please refer to the following image:

https://ibb.co/5nJNydw

This actually should be nested element.


Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13249
  • Karma: +554/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Please refer to the following image:

https://ibb.co/5nJNydw

This actually should be nested element.
You can't see that on a diagram, things get un-nested sometimes.
How does it look in the project browser? That is what shows the real nesting.

Geert

priombiswas89

  • EA User
  • **
  • Posts: 47
  • Karma: +0/-0
    • View Profile
Yes, I am trying to achieve it from referring to project browser. But still haven't been able to get the desired output.

qwerty

  • EA Guru
  • *****
  • Posts: 13584
  • Karma: +396/-301
  • I'm no guru at all
    • View Profile
It "looks" like these are the same, but you can only tell by actually issuing Alt-G on each to see where it lands in the browser.

q.

priombiswas89

  • EA User
  • **
  • Posts: 47
  • Karma: +0/-0
    • View Profile
I know and I can see the tree, somehow I am struggling to print the tree structure as mentioned in my original post. Any kind of help will be much appreciated.

qwerty

  • EA Guru
  • *****
  • Posts: 13584
  • Karma: +396/-301
  • I'm no guru at all
    • View Profile
Well, break it down to something that can be looked at. That pile of code is too much (for me).

q.

priombiswas89

  • EA User
  • **
  • Posts: 47
  • Karma: +0/-0
    • View Profile
Below is the snippet for getting element:

Code: [Select]
int elementId = diagramObj.ElementID;
EA.Element element = Rep.GetElementByID(elementId);

if (element.Elements.Count > 0)
{
  for (short ip = 0; ip < element.Elements.Count; ip++)
    {
        int parentId = 0;
        EA.Element child = (EA.Element)element.Elements.GetAt(ip);
        parentId = child.ParentID;
        EA.Element parent = Rep.GetElementByID(parentId);
        stateObj.name = $"{parent.Name}/{child.Name}";
        GetEmbeddedElement(child); // called the recursive method
      }
}

below is the recursive method:

Code: [Select]

private void GetEmbeddedElement(EA.Element element)
        {
            EA.Collection elements = element.Elements;
            for (short ip = 0; ip < elements.Count; ip++)
            {
                EA.Element child = (EA.Element)elements.GetAt(ip);
                GetEmbeddedElement(child);
            }
        }

« Last Edit: January 07, 2021, 08:14:40 am by priombiswas89 »

qwerty

  • EA Guru
  • *****
  • Posts: 13584
  • Karma: +396/-301
  • I'm no guru at all
    • View Profile
Well, and what would you expect? That operation recurses and returns without anything.

q.

priombiswas89

  • EA User
  • **
  • Posts: 47
  • Karma: +0/-0
    • View Profile
That's why actually I have posted the whole code above. I want to achieve below


Run/AliveQuery
Run/AliveQuery/State1
Run/WaitAliveResponse
Run/WaitAliveResponse/State2
Run/WaitAliveResponse/State2/State3


the reference image is as follows:


https://ibb.co/5nJNydw

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13249
  • Karma: +554/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
If you want the full path, you'll have to pass the part you already did to the function. Otherwise you won't be able to get more then parent/child

And you'll have to do something in your function, like actually print the full path

PS. this part is completely superfluous as you already have the parent element, the variable element
You are actually iterating the parent's children, and from each child you retrieve it's parent again.

Code: [Select]
parentId = child.ParentID;
EA.Element parent = Rep.GetElementByID(parentId);

priombiswas89

  • EA User
  • **
  • Posts: 47
  • Karma: +0/-0
    • View Profile
I have modified the code as below:

Code: [Select]
State stateObj = new State();
                                if (element.Elements.Count == 0)
                                {
                                    stateObj.name = element.Name;
                                }
                                stateObj.operations = new List<Operation>();
                                diagramElementsObj.states.Add(stateObj);

                                // To get nested elements
                                if (element.Elements.Count > 0)
                                {
                                    string parent = element.Name;
                                    for (short ip = 0; ip < element.Elements.Count; ip++)
                                    {
                                        EA.Element child = (EA.Element)element.Elements.GetAt(ip);
                                        stateObj.name= $"{parent}/{child.Name}";
                                        GetEmbeddedElement(child);
                                    }
                                }


private void GetEmbeddedElement(EA.Element element)
        {
            EA.Collection elements = element.Elements;
            for (short ip = 0; ip < elements.Count; ip++)
            {
                EA.Element child = (EA.Element)elements.GetAt(ip);
                GetEmbeddedElement(child);
            }

        }

and got the following output:


- name: off
- name: Boot
- name: Wait for HK
- name: Run/WaitAliveResponse
- name: AliveQuery/State1
- name: WaitAliveResponse/State2
- name: uPError
- name: Shutdown
- name: State1
- name: State2/State3
- name: State3


I am not sure but do I need to print it inside the recursive GetEmbeddedElement method?

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13249
  • Karma: +554/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
I'm not sure what you are trying to achieve with the GetEmbeddedElement method.
It' doesn't do anything.

Geert

priombiswas89

  • EA User
  • **
  • Posts: 47
  • Karma: +0/-0
    • View Profile
I am trying to get the path by calling this method. The path can be any level deep. As nesting can be done till any level, I need to do a recursion right? Or is there any api method that can return the path in Enterprise Architect?