Add Involved Functions to Capability via P4C

Hi there,

Would anyone be able to help me work out how to add ‘Abstract Function Abstract Capability involvement’ links using Python 4 Capella so I can add links between functions and capabilities I create? Here is the method defined in the simplified API to get involvements, but how would you set them?

def get_involved_functions(self) -> List[Function]:
    """
    Returns: Function[*]
    """
    res = []
    e_object_class = getattr(sys.modules["__main__"], "EObject")
    for involvment in self.get_java_object().getOwnedFunctionalChainInvolvements():
        if involvment.eClass().getName() == 'FunctionalChainInvolvementFunction':
            involvedElement = involvment.getInvolvedElement()
            if involvedElement is not None:
                specific_cls = e_object_class.get_class(involvedElement)
                res.append(specific_cls(involvedElement))
    return res

Thanks in advance.

Kind regards

Jack

Just to clarify here, it looks like this function is getting the involvement of functions in Functional Chains, not in Capabilities.
Stephane

Hi Stephane,

Thank you for reaching out. Sorry yes you are right. I was also looking at functional chains which are also proving difficult to create and link up to functions. Here is a method defined to retrieve the involved_functions from the simplified_api class AbstractSystemCapability:

def get_involved_functions(self) -> List[Function]:
    """
    Returns: Function[*]
    """
    return create_e_list(self.get_java_object().getInvolvedAbstractFunctions(), Function)

I’ve downloaded Capella 6.1’s source code and had a look through in Capella Studio for potential methods starting with some of the java functions defined above with the intent to reverse engineer how the ‘Abstract Function Abstract Capability Involvement’ links are created. Please let me know if you can help, or have any advice on how to interrogate the source code as this is a new endeavor for me…

Many Thanks

Jack

So:
Maybe an easier way for you to find the right methods is to use the Sirius interpreter - more on this in the Python4Cpaella Tips and tricks section https://github.com/labs4capella/python4capella/blob/master/doc/org.eclipse.python4capella.doc/doc/user/general/TipsAndTricks.textile - look for “Finding Java methods”

The involvedAbstractFunctions used in the previous code is a “derived” feature on Capabilities, meaning that it is calculated. So you cannot use it to “add functions” to it. In reality, when you have an involvement between a Capability and a function, an AbstractFunctionAbstractCapabilityInvolvement object is created in the model, linking the Capability to the function.

So the algorithm to create an involvement link between a myFunction and a myCapability would look like:

  • Create an AbstractFunctionAbstractCapabilityInvolvement object (let’s call it myInvolvement)
  • myInvolvement.setCapability(myCapability)
  • myInvolvement.setFunction(myFunction)
    (and of course this has to be called in a try catch statement within a model transaction, same as usual when modifying a model with PYthon4Capella)
    Stephane

Actually, my previous message was not exactly right - here is some code that will work:

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

aird_path = "/MyTest/MyTest.aird"

model = CapellaModel()
model.open(aird_path)

# gets the SystemEngineering
se = model.get_system_engineering()

# start a transaction to modify the Capella model
model.start_transaction()
try:
    #Create an AbstractFunctionAbstractCapabilityInvolvement object in the model
    e_class = get_e_classifier("http://www.polarsys.org/capella/core/interaction/" + capella_version(), "AbstractFunctionAbstractCapabilityInvolvement")
    myInvolvement = create_e_object_from_e_classifier(e_class)
    
    #Hard-coded for the sake of this test (getting the fist Capability and the first System function in the SA
    #Note that we are getting the java object here
    myCapability = se.get_system_analysis().get_all_contents_by_type(Capability)[0].get_java_object()
    myFunction = se.get_system_analysis().get_all_contents_by_type(Function)[1].get_java_object()

    #Links the Capability to the Function using the AbstractFunctionAbstractCapabilityInvolvement previously created
    myCapability.getOwnedAbstractFunctionAbstractCapabilityInvolvements().add(myInvolvement) 
    myInvolvement.setInvolved(myFunction)

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()

1 Like

Hi Stephane,

Thank you very much for solving this one, I’ve been experimenting in the background without much success apart from learning what doesn’t work! This e_class = get_e_classifer… and creat_e_object_from_e_classifier(e_class) looks like a powerful combination with the interpreter tip you gave earlier. Thanks again.

Best regards

Jack

Glad it helped.
You will see a lot of these get_e_classifer if you look at the Capella.py file.
Stephane

Hi Stephane,

Struggling with one more issue, tried to extend this to Operational Entity Capability Involvement links. Here’s my modified code:

# Get the System Engineering and Operational Analysis
se = model.get_system_engineering()
op = se.get_operational_analysis()
op_act_pkg = op.get_operational_activity_pkg()
op_cap_pkg = op.get_operational_capability_pkg()
op_ent_pkg = op.get_entity_pkg()

# Start a transaction to modify the Capella model
model.start_transaction()

try:
    #Create an EntityOperationalCapabilityInvolvement object in the model
    e_class = get_e_classifier("http://www.polarsys.org/capella/core/oa/" + capella_version(), "EntityOperationalCapabilityInvolvement")
    myInvolvement = create_e_object_from_e_classifier(e_class)
    print(myInvolvement)
    #Hard-coded for the sake of this test (getting the first Operational Capability and the first operational Activity in the OA
    #Note that we are getting the java object here
    myCapability = op_cap_pkg.get_all_contents_by_type(OperationalCapability)[1].get_java_object()
    print(myCapability.getName())
    myEntity = op_ent_pkg.get_all_contents_by_type(OperationalEntity)[1].get_java_object()
    print(myEntity.getName())
    #Links the Capability to the Function using the EntityOperationalCapabilityInvolvementpreviously created
    myCapability.getEntityOperationalCapabilityInvolvement().add(myInvolvement) 
    myInvolvement.setInvolved(myEntity)

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()

All seems to be going well till I get an error for this line of code:

myCapability.getEntityOperationalCapabilityInvolvement().add(myInvolvement)

However looks like it should work from the Interpreter query and the source code

	@Override
	public EClass getEntityOperationalCapabilityInvolvement() {
		return entityOperationalCapabilityInvolvementEClass;
	}

Here’s the error:

 File "C:\6_1\capella\plugins\py4j-python_0.10.9.5-bnd-2odeag\src\py4j\java_gateway.py", line 1321, in __call__
    return_value = get_return_value(
                   ^^^^^^^^^^^^^^^^^
  File "C:\6_1\capella\plugins\py4j-python_0.10.9.5-bnd-2odeag\src\py4j\java_gateway.py", line 1321, in __call__
    return_value = get_return_value(
                   ^^^^^^^^^^^^^^^^^
  File "C:\6_1\capella\plugins\py4j-python_0.10.9.5-bnd-2odeag\src\py4j\protocol.py", line 330, in get_return_value
    raise Py4JError(
py4j.protocol.Py4JError: An error occurred while calling o189.getEntityOperationalCapabilityInvolvement. Trace:
py4j.Py4JException: Method getEntityOperationalCapabilityInvolvement([]) does not exist
	at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:318)

Any ideas on how to tackle this one?

Best regards

Jack

use getOwnedEntityOperationalCapabilityInvolvements instead

That works, thank you very much for the help. Tried “s” at the end but didn’t try “Owned”. Cheers. Jack