Logical component generation using python4 capella

Hi all,
I am using the .add() method on a logical component object to update the logical architecture of a (currently empty) Capella model. I am successfully adding the logical components to the Capella model and these appear in the Capella model when I open the project. However these logical components (or coffee machine in my example below) do not have any entries in their “representing parts” or “Typed Elements” properties, nor do they appear in their parents “contained parts” or “sub logical components” properties.
As a result, the logical components I add to the model in this way can’t be added to any Logical Architecture Diagrams [LAB]. Is there a workaround for this?

This is a stripped-down version of the script I am using that should recreate the issue:

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

ws = {'Coffee_Machine'}


model = capella.CapellaModel()
model.open('/blank_project/blank_project.aird')

# gets the SystemEngineering
se = model.get_system_engineering()

# get the root logical component
la_ls = se.get_logical_architecture().get_logical_system()

# start a transaction to modify the Capella model
model.start_transaction()
try:
    # create physical components with the list of names in the components list
    for component in ws:
        # create a logical component
        lc = LogicalComponent()
        #set its name
        print("* Create a new logical component with name " + component)
        lc.set_name(component)
        #add the new PhysicalComponent
        la_ls.get_owned_logical_components().add(lc)
except:
    # if something went wrong we rollback the transaction
    model.rollback_transaction()
    raise
else:
    # if everything is ok we commit the transaction
    model.commit_transaction()

# save the Capella model
model.save()

Thanks for any help with this

I suspect that instead of using:

la_ls = se.get_logical_architecture().get_logical_system()

You should use:

la_ls = se.get_logical_architecture().get_logical_component_pkg()

Stephane Lacrampe
ObeoSoft Canada

Hi Stephane,
thanks for the help, I have made that change but sadly no luck. Are there any available functions for specifically defining typed elements?

my current code is:

# 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 *

ws = {'Coffee_Machine'}


model = CapellaModel()
model.open('/blank_project/blank_project.aird')

# gets the SystemEngineering
se = model.get_system_engineering()

# get the root logical component
la_ls = se.get_logical_architecture().get_logical_component_pkg()

# start a transaction to modify the Capella model
model.start_transaction()
try:
    # create physical components with the list of names in the components list
    for component in ws:
        # create a logical component
        lc = LogicalComponent()
        #set its name
        print("* Create a new logical component with name " + component)
        lc.set_name(component)
        #add the new PhysicalComponent
        la_ls.get_owned_logical_components().add(lc)
except:
    # if something went wrong we rollback the transaction
    model.rollback_transaction()
    raise
else:
    # if everything is ok we commit the transaction
    model.commit_transaction()

# save the Capella model
model.save()
# get the rootlogicalComponent
la_ls = se.get_logical_architecture().get_logical_system()
for lc in la_ls.get_owned_logical_components():
    print(f'logical components owned by the logical system: {lc.get_name()}')
1 Like

There is no API to manipulate Part in the Python API. You can use the Java API to do something like:

java_part = create_e_object_from_e_classifier(get_e_classifier("http://www.polarsys.org/capella/core/cs/" + capella_version(), "Part"))
java_part.setType(lc.get_java_object())
la_ls.get_java_object().getOwnedParts().add(java_part)
1 Like

Hi YvanLussaud,
thanks for your help, where should I import the create_e_object_from_e_classifier function from (I don’t seem to be able to see it in the python4capella packages)?
Or is this something I need to define myself?

Yes sorry, it should be:

java_part = create_e_object("http://www.polarsys.org/capella/core/cs/" + capella_version(), "Part")
1 Like

Great thanks very much, that all works now for me

1 Like

Hi YvanLussaud,
I also want to create logical components by p4c, and I used the following code,

java_part = create_e_object_from(get_e_classifier("http://www.polarsys.org/capella/core/cs/" + capella_version(), "Part"))
java_part.setType(lc.get_java_object())
lc_pkg.get_java_object().getOwnedParts().add(java_part)

but Capella reported an error, like this

raise Py4JError(
py4j.protocol.Py4JError: An error occurred while calling o46.setType. Trace:
py4j.Py4JException: Method setType([class org.polarsys.capella.core.data.la.impl.LogicalComponentImpl]) does not exist

I used the following code to check the methods of “java_part”, but I cannot find “setType”.

print(dir(java_part))

output:
['basicGetAbstractType', 'basicGetAssociation', 'basicGetOwnedAbstractType',
 'basicGetStatus', 'basicGetType', 'basicSetOwnedAbstractType', 
'basicSetOwnedDefaultValue', 'basicSetOwnedMaxCard', 
'basicSetOwnedMaxLength', 'basicSetOwnedMaxValue', 
'basicSetOwnedMinCard', 'basicSetOwnedMinLength', 'basicSetOwnedMinValue', 
'basicSetOwnedNullValue', 
'destroy', 'eAdapters', 'eAllContents', 'eBaseStructuralFeatureID', 
'eBasicRemoveFromContainer', 'eBasicRemoveFromContainerFeature', 
'eBasicSetContainer', 'eClass', 'eContainer', 'eContainerFeatureID',
 'eContainingFeature', 'eContainmentFeature', 'eContains', 'eContents',
 'eCrossReferences', 'eDeliver', 'eDerivedOperationID', 
'eDerivedStructuralFeatureID', 'eDirectResource', 
'eDynamicBasicRemoveFromContainer', 'eDynamicGet', 
'eDynamicInverseAdd', 'eDynamicInverseRemove', 'eDynamicInvoke', 
'eDynamicIsSet', 'eDynamicSet', 'eDynamicUnset', 'eGet', 'eInternalContainer', 
'eInternalResource', 'eInverseAdd', 'eInverseRemove', 'eInvoke', 'eIsProxy', 
'eIsSet', 'eNotificationRequired', 'eNotify', 'eObjectForURIFragmentSegment', 
'eOpenGet', 'eOpenIsSet', 'eOpenSet', 'eOpenUnset', 'eProxyURI', 
'eResolveProxy', 'eResource', 'eSet', 'eSetClass', 'eSetDeliver', 
'eSetProxyURI', 'eSetResource', 'eSetStore', 'eSetting', 'eStore', 
'eURIFragmentSegment', 'eUnset', 'eVirtualGet', 'eVirtualIsSet', 
'eVirtualSet', 'eVirtualUnset', 'equals', 'getAbstractType', 'getAggregationKind', 'getAppliedPropertyValueGroups', 'getAppliedPropertyValues', 
'getAppliedRequirements', 'getAssociation', 'getClass', 'getConstraints', 
'getDeployedParts', 'getDeployingLinks', 'getDeployingParts', 'getDeploymentLinks', 
'getDescription', 'getFeatures', 'getFullLabel', 'getId', 'getIncomingInformationFlows', 'getIncomingTraces', 'getInformationFlows', 'getInvolvingInvolvements', 'getLabel', 'getName', 'getOutgoingInformationFlows',
 'getOutgoingTraces', 'getOwnedAbstractType', 'getOwnedConstraints', 
'getOwnedDefaultValue', 'getOwnedDeploymentLinks', 'getOwnedEnumerationPropertyTypes', 
'getOwnedExtensions', 'getOwnedMaxCard', 'getOwnedMaxLength', 
'getOwnedMaxValue', 'getOwnedMigratedElements', 'getOwnedMinCard', 
'getOwnedMinLength', 
'getOwnedMinValue', 'getOwnedNullValue', 'getOwnedPropertyValueGroups', 'getOwnedPropertyValues', 'getProvidedInterfaces', 'getRepresentingInstanceRoles', 'getRequiredInterfaces', 
'getReview', 'getSid', 'getStatus', 'getSummary', 'getType', 'getVisibility',
 'hasUnnamedLabel', 'hashCode', 'isFinal', 'isIsAbstract', 'isIsDerived', 
'isIsPartOfKey', 'isIsReadOnly', 'isIsStatic', 
'isMaxInclusive', 'isMinInclusive', 'isOrdered', 'isUnique', 'isVisibleInDoc',
 'isVisibleInLM', 'notify', 'notifyAll', 'setAbstractType', 'setAggregationKind', 
'setDescription', 'setFinal', 
'setId', 'setIsAbstract', 'setIsDerived', 'setIsPartOfKey', 'setIsReadOnly',
 'setIsStatic', 'setMaxInclusive', 'setMinInclusive', 'setName', 'setOrdered', 
'setOwnedAbstractType', 'setOwnedDefaultValue', 'setOwnedMaxCard', 
'setOwnedMaxLength', 'setOwnedMaxValue',
 'setOwnedMinCard', 'setOwnedMinLength', 'setOwnedMinValue', 
'setOwnedNullValue', 'setReview', 'setSid', 'setStatus', 'setSummary', 
'setUnique', 'setVisibility', 'setVisibleInDoc', 'setVisibleInLM', 'toString',
 'wait']

Could you tell me which method is correct?

I found an utility method from the Capella Java code to run the same code as Capella after a CapellaElement is create and attached to the Capella model. It will create and set the Part for you.

            #add the new PhysicalComponent
            pc_pkg.get_owned_physical_components().add(pc)
            org.polarsys.capella.core.model.helpers.CapellaElementExt.creationService(pc.get_java_object())

Here the example is for a PhysicalComponent but you can adapt it for LogicalComponent. This method can be used for any CapellaElement I think. You just need to make sure the CapellaElement has been added to the Capella model before calling the creation service.

1 Like

Excellent! This is what I want. Codes is working. In addition, I found if I want to set the LogicalComponent’s name, I should write the sentences after the Capella Java code.
Great thanks very much.

1 Like