Adding Diagram Element Links via Script

Hey,

I’m trying to add a diagram element link into the description of our components. We have a large number of components and there is also a large number of diagrams that are used for each component.

I can obtain the diagrams of interest and write the diagram names into the description as text but can’t seem to find a useful function within the Capella Library that might help me achieve this. Is this possible to do?

For context, here is the function below in case anyone else wants to use this in the future.

# create hashmap of elements
sbs_elements = {}
for pkg in PCs:
    for pab in pkg.get_owned_diagrams():
        if pab.get_name() == sbs:
            for comp in pab.get_represented_elements():

                if "BehaviorPC" in str(comp) or "NodePC" in str(comp): # can use isinstance() here
                    sbs_elements[comp.get_name()] = [comp.get_description()]

# update hashmap with diagram names for each key
for diag in model.get_all_diagrams():
    if "[PAB]" in diag.get_name() and "SBS" not in diag.get_name() and "SWBS" not in diag.get_name():
        print(f"Checking {diag.get_name()}")
        try:
            for comp in diag.get_represented_elements():
                if "BehaviorPC" in str(comp) or "NodePC" in str(comp):
                    comp_name = comp.get_name().split(':', 1)[0]
                    add_value_to_key(sbs_elements, comp_name, diag.get_name())
        except:
            print(diag.get_name(), "broken")

model.start_transaction()
try:         
    for diag in model.get_all_diagrams():
        if diag.get_name() == diagram_name:
            print(f"Checking {diag.get_name()}")
            for comp in diag.get_represented_elements():
                if "BehaviorPC" in str(comp) or "NodePC" in str(comp):
                    try:
                        comp_name = comp.get_name().split(':', 1)[0]
                        print(f"{comp_name} current description: {comp.get_description()}")
                        print(f"Setting to new description {sbs_elements[comp_name]}")
                        desc = ""
                        for val in sbs_elements[comp_name]:
                            desc += val + "\n" # this doesn't actually add a new line...

                        comp.set_description(desc)
                       
                    except:
                        pass
except:
    # if something went wrong we rollback the transaction
    print("Rollbacking transaction")
    model.rollback_transaction()
    raise
else:
    # if everything is ok we commit the transaction
    print("committing transaction")
    model.commit_transaction()


This is what I want to be able to automate and add into the description ^

I imagine there’s something that I can query that will allow me to find the diagram I’m interested in and then also just create the link with the diagram name as the title.

Ok, I figured it out, turns out that URL ID is just the UID (obviously) of the diagram. I can just use markdown to set a link. For anyone interested and needs to do this in the future, here’s the code:

def add_value_to_key(dictionary, key, value):
    if key not in dictionary:
        dictionary[key] = value
    elif isinstance(dictionary[key], list):
        if value not in dictionary[key]:
            dictionary[key].append(value)
    else:
        dictionary[key] = [dictionary[key], value]

# create hashmap of elements
sbs_elements = {}
for pkg in PCs:
    for pab in pkg.get_owned_diagrams():
        if pab.get_name() == sbs:
            for comp in pab.get_represented_elements():

                if "BehaviorPC" in str(comp) or "NodePC" in str(comp): # can use isinstance() here
                    sbs_elements[comp.get_name()] = [comp.get_description()]

# update hashmap with diagram names for each key
for diag in model.get_all_diagrams():
    if "[PAB]" in diag.get_name() and "SBS" not in diag.get_name() and "SWBS" not in diag.get_name():
        print(f"Checking {diag.get_name()}")
        try:
            for comp in diag.get_represented_elements():
                if "BehaviorPC" in str(comp) or "NodePC" in str(comp):
                    comp_name = comp.get_name().split(':', 1)[0]
                    add_value_to_key(sbs_elements, comp_name, diag)
        except:
            print(diag.get_name(), "broken")

model.start_transaction()
try:         
    for diag in model.get_all_diagrams():
        if diag.get_name() == diagram_name:
            print(f"Checking {diag.get_name()}")
            for comp in diag.get_represented_elements():
                if "BehaviorPC" in str(comp) or "NodePC" in str(comp):
                    try:
                        comp_name = comp.get_name().split(':', 1)[0]
                        print(f"{comp_name} current description: {comp.get_description()}")
                        print(f"Setting to new description {sbs_elements[comp_name]}")
                        desc = ""
                        for val in sbs_elements[comp_name]:
                            uid = val.get_uid()
                            diag_name = val.get_name()
                            desc += f'<p><a href="hlink://{uid}"><font color="#0066cc">{diag_name}</font></a></p>'

                        comp.set_description(desc)
                       
                    except:
                        pass
except:
    # if something went wrong we rollback the transaction
    print("Rollbacking transaction")
    model.rollback_transaction()
    raise
else:
    # if everything is ok we commit the transaction
    print("committing transaction")
    model.commit_transaction()

Realised I didn’t add one of my functions. If you have any improvements for this script, would love the input.

2 Likes