How to Create Logical Functions Within Logical Components via Python4Capella?

Hello,

I’m trying to write a script that would create two logical components, comp1 and comp2, each containing the logical functions F1 and F2 respectively. I also want to link F2 to F1 with a Functional Exchange (for example, from F1 to F2). My script works up to the creation of the two logical components and a Component Exchange between them, but it stops working when I try to create the functions F1 and F2. The console often returns an error related to the class “Allocation”. I’m sharing the entire script, even though the most relevant part starts at the line #Creating logical functions.

Could you help me fix this issue?

Here is my script:

#include needed for the Capella modeller API
include(‘workspace://Python4Capella/simplified_api/capella.py’)
if False:
from simplified_api.capella import *

#include needed for utilities
include(‘workspace://Python4Capella/utilities/CapellaPlatform.py’)
if False:
from utilities.CapellaPlatform import *

#Path to my Capella project
path = ‘/Projet/Projet.aird’

#Opening the model
model = CapellaModel()
model.open(path)

#Starting a transaction
model.start_transaction()

#Retrieving the Logical Architecture
system_engineering = model.get_system_engineering()
logical_architecture = None
for element in system_engineering.get_contents():
if isinstance(element, LogicalArchitecture):
logical_architecture = element
break

if logical_architecture is None:
raise Exception(“can not find Logical Architecture in the model.”)

#Retrieving the interface package from the Logical Architecture
interface_pkg = logical_architecture.get_interface_pkg()
if interface_pkg is None:
raise Exception(“can not find InterfacePkg in Logical Architecture”)

#=== Creating logical components in the Logical System ===
logical_system = logical_architecture.get_logical_system()
if logical_system is None:
raise Exception(“can not find Logical System in Logical Architecture”)

comp1 = LogicalComponent()

logical_system.get_java_object().getOwnedLogicalComponents().add(comp1.get_java_object())
#replicate the Capella behavior, this will create the Component Part
org.polarsys.capella.core.model.helpers.CapellaElementExt.creationService(comp1.get_java_object())
comp1.set_name(“COMP1”)

comp2 = LogicalComponent()
logical_system.get_java_object().getOwnedLogicalComponents().add(comp2.get_java_object())
#replicate the Capella behavior, this will create the Component Part
org.polarsys.capella.core.model.helpers.CapellaElementExt.creationService(comp2.get_java_object())
comp2.set_name(“COMP2”)

#creation of the ports
cp1 = ComponentPort()
cp1.set_name(“port1”)
cp1.set_orientation(“INOUT”)

cp1.set_kind(“FLOW”) # ou ‘PHYSICAL’

#adding port 1 to comp1 via EMF
comp1.get_java_object().getOwnedFeatures().add(cp1.get_java_object())

org.polarsys.capella.core.model.helpers.CapellaElementExt.creationService(cp1.get_java_object())

cp2 = ComponentPort()
cp2.set_name(“port2”)
cp2.set_orientation(“INOUT”)

cp2.set_kind(“FLOW”) # ou ‘PHYSICAL’

#adding port 2 to comp2 via EMF
comp2.get_java_object().getOwnedFeatures().add(cp2.get_java_object())
org.polarsys.capella.core.model.helpers.CapellaElementExt.creationService(cp2.get_java_object())

ce = ComponentExchange()

ce.get_java_object().setSource(cp1.get_java_object())
ce.get_java_object().setTarget(cp2.get_java_object())

#adding ComponentExchange to the Logical System via EMF
logical_system.get_java_object().getOwnedComponentExchanges().add(ce.get_java_object())
org.polarsys.capella.core.model.helpers.CapellaElementExt.creationService(ce.get_java_object())

#Creating logical functions
logical_function_pkg = logical_architecture.get_logical_function_pkg()
if logical_function_pkg is None:
raise Exception(“Cannot find LogicalFunctionPkg in Logical Architecture”)

#F1
f1 = LogicalFunction()
f1.set_name(“F1”)
logical_function_pkg.get_java_object().getOwnedLogicalFunctions().add(f1.get_java_object())
org.polarsys.capella.core.model.helpers.CapellaElementExt.creationService(f1.get_java_object())

#F2
f2 = LogicalFunction()
f2.set_name(“F2”)
logical_function_pkg.get_java_object().getOwnedLogicalFunctions().add(f2.get_java_object())
org.polarsys.capella.core.model.helpers.CapellaElementExt.creationService(f2.get_java_object())

#Allocation
alloc1 = Allocation()
alloc1.set_source_element(f1) # source = fonction
alloc1.set_target_element(comp1) # target = composant
logical_system.get_java_object().getOwnedTraces().add(alloc1.get_java_object())
org.polarsys.capella.core.model.helpers.CapellaElementExt.creationService(alloc1.get_java_object())

alloc2 = Allocation()
alloc2.set_source_element(f2)
alloc2.set_target_element(comp2)
logical_system.get_java_object().getOwnedTraces().add(alloc2.get_java_object())
org.polarsys.capella.core.model.helpers.CapellaElementExt.creationService(alloc2.get_java_object())

#Creating the functional exchange
fe = FunctionalExchange()
fe.set_name(“FE_F1_to_F2”)
fe.get_java_object().setSource(f1.get_java_object())
fe.get_java_object().setTarget(f2.get_java_object())

#Adding the Functional Exchange to LogicalFunctionPkg
logical_function_pkg.get_java_object().getOwnedFunctionalExchanges().add(fe.get_java_object())
org.polarsys.capella.core.model.helpers.CapellaElementExt.creationService(fe.get_java_object())

#Commit the transaction.
model.commit_transaction()

#Saving the model
model.save()

print(“COMP1 & COMP2 successfully created”)

Thank you.

The EClass Allocation is abstract, you need to use the ComponentFunctionalAllocation:

lc = LogicalComponent()
lf = LogicalFunction()
cfa = ComponentFunctionalAllocation()
cfa.get_java_object().setSourceElement(lc.get_java_object())
cfa.get_java_object().setTargetElement(lf.get_java_object())
lc.get_java_object().getOwnedFunctionalAllocation().add(cfa.get_java_object())

Here we need to use Java API.

Thank you. I adapted the code to my script, but I’m still encountering an issue. After running the script, when I open a LAB diagram and place my logical component, then try to display the function allocated to it via “Allocated Functions,” Capella does show the function created by the script in the list. However, when I confirm, it doesn’t appear inside the component, as if it didn’t exist. Moreover, when I restart Capella, the function completely disappears from the “Allocated Functions” list and no longer exists anywhere. Do you know what could be causing this?

I’m not sure what is going wrong but you might need to put your LogicalFunction in the “Root Logical Function”:

logical_function_pkg.get_owned_logical_functions()[0].get_owned_functions().add(f1)
logical_function_pkg.get_owned_logical_functions()[0].get_owned_functions().add(f2)

But something else might be missing. You can try to create a Capella model by hand and look at the XMI serialization in the *.capella file. See if something is present in the model that is not created by your script.

Ah thanks, that was indeed it! It finally works.

1 Like

Would you know how to properly create a Functional Exchange between two functions F1 and F2 that I have defined in the script?

I wrote the following code, but it doesn’t work because, according to the console, adding fe to LogicalFunctionalPkg is not done this way.

#Creating the Functional Exchange
fe = FunctionalExchange()
fe.set_name(“FE_F1_to_F2”)

#Defining source and target
fe.get_java_object().setSource(F1.get_java_object())
fe.get_java_object().setTarget(F2.get_java_object())

#Adding fe to LogicalFunctionalPkg
logical_function_pkg.get_java_object().getOwnedFunctionalExchanges().add(fe.get_java_object())

#Replicating the behaviour in Capella
org.polarsys.capella.core.model.helpers.CapellaElementExt.creationService(fe.get_java_object())

FunctionalExhange needs to be contained by the common LogicalFunction ancestor of the source and target LogicalFunction. Just like you did with LogicalComponent and the ComponentExchange.
In your case if you added both LogicalFunction to the “Root Logical Function”, then you can use the “Root Logical Function” to store your FunctionalExhange.

Ok I see. So I replaced my line by:

logical_function_pkg.get_owned_logical_functions()[0].get_owned_functions().add(fe)

But I’m dealing with a new issue:

The issue is that I cannot use the functions in capella.py dedicated to handling Capella functions for the Functional Exchange, and when I combine them with getOwnedFunctionalExchanges, it doesn’t work either. I don’t know which function to use.

I often struggle to find the right functions to use in my Python4Capella scripts.
Do you have a website or a guide you could recommend where all the functions are described, so I can learn how to do things properly?

When writing my scripts, I only rely on what I can see and understand from the plugin scripts like capella.py, and I also use Copilot for help. I really don’t understand how one is supposed to know which functions to use and in which cases.

You can do something like:

fe = FunctionalExchange()
root_function.get_owned_functional_exchanges().add(fe)

I just tried root_function, but it’s not an existing variable:

image

I also tried with logical_function_pkg, but it doesn’t recognize the function get_owned_functional_exchanges:

image

The root function is the only function directly contained by the logical_function_pkg:

root_logical_function = model.get_system_engineering().get_logical_architecture().get_logical_function_pkg().get_owned_logical_functions()[0]

It works, thank you very much!

1 Like