Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a get_children method #337

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Add a get_children method #337

wants to merge 4 commits into from

Conversation

Wuestengecko
Copy link
Member

This new method helps with introspecting the model, and lets library
clients more easily interact with objects of different types without
having to constantly cross-reference the metamodel.

This new method helps with introspecting the model, and lets library
clients more easily interact with objects of different types without
having to constantly cross-reference the metamodel.
@Wuestengecko Wuestengecko marked this pull request as ready for review September 25, 2023 13:05
@jamilraichouni jamilraichouni self-requested a review September 25, 2023 19:07
Copy link
Contributor

@jamilraichouni jamilraichouni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All I get listed from capellambse for the test model (https://github.com/DSD-DBS/py-capellambse/blob/487246a9e82717e7929a700d9c103b73f57f16d0/tests/data/melodymodel/6_0/Melody%20Model%20Test.aird) on the OA layer has been marked in the Project Explorer. There is a Role Pkg and its child missing:

image

@jamilraichouni
Copy link
Contributor

The layer "EPBS Architecture" is not considered.

@jamilraichouni
Copy link
Contributor

jamilraichouni commented Sep 25, 2023

Is there a way to get the so called "System Engineering" (selection on the screenshot) as kind of top level/ root node from which one can start to walk through all levels via get_children()?

image

Its .get_children() could return the layers

  • model.oa
  • model.sa
  • model.la
  • model.pa
  • model.epbs

BTW:
The "System Engineering" element itself can have a description. In Capella it is possible to get/ set the description of the "System Engineering" entity. That should also be possible with capellambse (note that the description editor of Capella is very buggy).

@Wuestengecko
Copy link
Member Author

There is a Role Pkg and its child missing:

The layer "EPBS Architecture" is not considered.

These are probably just not yet covered by the current metamodel implemented in capellambse.

Is there a way to get the so called "System Engineering" (selection on the screenshot) as kind of top level/ root node from which one can start to walk through all levels via get_children()?

Not easily (yet), but this will change with the (ongoing) model rework.

The best workaround I can currently offer is:

syseng = model.search("org.polarsys.capella.core.data.capellamodeller:SystemEngineering")[0]

@jamilraichouni
Copy link
Contributor

jamilraichouni commented Sep 28, 2023

import capellambse                                                                 
                                                                                     
model = capellambse.MelodyModel(                                                   
    "tests/data/melodymodel/6_0/Melody Model Test.aird"                            
)                                                                                  
                                                                               
                                                                                     
def walk(item):                                                                    
    _ = [walk(i) for i in item.get_children()]                                     
                                                                                     
                                                                                 
walk(model.sa)

crashes

Guess it's easy to reproduce. Nevertheless, a pic:

image

Doing the same with walk(model.la) is also crashing. walk(model.oa) and walk(model.pa) run through for the given test model.

@jamilraichouni
Copy link
Contributor

jamilraichouni commented Sep 28, 2023

I created two text files with a tree structure for the four layers OA, SA, LA, PA (attached) and took the test model:

ease.txt
capellambse.txt

The file ease.txt has been created using EASE. It represents the output of display names for all items (recursive walk) in the project explorer.

Look at a text diff for the .txt files, please!

Check for orphan blocks and diffs. I think there can sth. be done to align the outputs a bite more.

To recreate the file capellambse.txt you can adapt and run the following not beautiful but working code:

"Walk through all items in Capella model." ""
import pathlib
import typing as t

import capellambse

INDENT = 2
OUTPUT = ""


class _Item:
    def __init__(self, display_name, get_children):
        self.display_name = display_name
        self.get_children = get_children


def _walk(item, level=0):
    # pylint: disable-next=global-statement
    global OUTPUT

    current_output = INDENT * " " * level + item.display_name
    OUTPUT += "\n" + current_output
    items = []
    items_ = item.get_children()
    for item_ in items_:
        display_name = (
            item_.name
            if item_.name is not None and item_.name
            else f"[{item_.__class__.__name__}]"
        )
        _item = _Item(display_name, item_.get_children)
        items.append(_item)
    items = sorted(items, key=lambda x: x.display_name)
    for item_ in items:
        _walk(item_, level + 1)


def _main():
    model = capellambse.MelodyModel(
        "tests/data/melodymodel/6_0/Melody Model Test.aird"
    )
    _walk(_Item("Logical Architecture", model.la.get_children))
    _walk(_Item("Operational Analysis", model.oa.get_children))
    _walk(_Item("Physical Architecture", model.pa.get_children))
    _walk(_Item("System Analysis", model.sa.get_children))


if __name__ == "__main__":
    _main()
    pathlib.Path("capellambse.txt").write_text(OUTPUT, encoding="utf8")

Neovim/ Vim users may want to run

vim -d ease.txt capellambse.txt

@Wuestengecko
Copy link
Member Author

A part of the differences can easily be explained by some different design choices in capellambse compared to Capella (left side ease.txt, right side capellambse.txt):

capellambse.txt --- 1/12 --- Text
 3     Capability Realization            3     Capability Realization
 4       Scenario                        4       Scenario
 5         Whomping Willow               5         Whomping Willow
 6         [ES] Exchange Scenario        .

This is a bit misleading in the Project Explorer – Diagrams aren't actually located anywhere in the "semantic" tree, but Capella displays diagrams as children of their target object.

I don't think it makes sense to add them to the get_children() return value, but if you really want them to show up, you could simply ask for obj.diagrams in addition to obj.get_children().


capellambse.txt --- 4/12 --- Text
118   Structure                          86   Structure
119     Harry J. Potter                  87     Harry J. Potter
120       CP 1                           88       CP 1
121         [Port Allocation] to FIP 1   ..
122       CP 2                           89       CP 2
123         [Port Allocation] to FIP 1   ..
124       CP 3                           90       CP 3
125         [Port Allocation] to FIP 2   ..
... snip ...

This one's easy: PortAllocation (basically everything named SomethingAllocation, or something with Involvement in the name) only describes a relation to another model object, and doesn't provide any other new information to the model. The default filters hide these from the Project Explorer, and capellambse doesn't expose them as "real objects" at all.


220 Operational Analysis                128 Operational Analysis
221   Additional Types                  ...
222     Other                           ...
223     Other Module                    ...
224   Data                              129   Data
225     /cmd_vel                        ...
226       ExchangeItemElement 1: Twist  ...
227         [maxCard]  = 1              ...
228         [minCard]  = 1              ...
229       ExchangeItemElement 2: <undef ...
... ined>                               ...
230         [maxCard]  = 1              ...
231         [minCard]  = 1              ...
232     ExchangeItem 1                  ...
233     ExchangeItem 2                  ...
234     ExchangeItem 3                  ...
235     ExchangeItem 4                  ...
236     ExchangeItem 5                  ...
237     ExchangeItem 6                  ...
238     Twist                           130     Twist
239     [CDB] Data                      ...
240     good advise                     ...
241     not so good advise              ...
242   Interfaces                        131   Interfaces
243   Module                            132   Next Module
244     This is a folder.               ...
245       Subfolder                     ...
246         TestReq3                    ...
247           [undefined] Sysexfunc     ...
248       Test requirement 1 really l o ...
...  n g text that is way too long to d ...
... isplay here as t...                 ...
249         [AttrDef] 10                ...
250         [AttrDef] 10.5              ...
251         [AttrDef] Fri Jul 23 15:00: ...
... 00 GMT+02:00 2021                   ...
252         [AttrDef] Test              ...
253         [AttrDef] true              ...
254         [Boolean Value Attribute] f ...
... alse                                ...
255         [RelationType] TypedReq1    ...
256         [RelationType] Weather      ...
257         [undefined] Sysexfunc       ...
258       TypedReq2                     ...
259         [AttrDef] null              ...
260         [MultiEnum] enum_val1, enum ...
... _val2                               ...

This one's easy to explain as well: This is simply missing from our metamodel definition, that's why the get_children() function can't find it. We need to add these objects and types to our metamodel.

The missing Requirements might also have a different explanation, which is that capellambse couldn't load the extension. Did you properly install capellambse? Remember that you need to run pip install -e . to generate some metadata after git clone-ing the repo.

This can improve performance when one just needs to know, if an item
has children.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants