Removing Relations from requirements

Hi,
I need to setup a script to update allocation of requirements to components in accordance with imported ReqIF. I am working on Capella 7.0 with Python4Capella 1.3.0 and python 3.10.13.
I defined a relation named “Allocated to”
I would like to remove existing allocations

    for req in m.get_owned_requirements():
            logging.info("Reassigning requirement %s", req.get_attribute('IE PUID').get_value())

            rels = req.get_owned_relations()
            for rel in rels:
                if rel.get_relation_type()[0].get_long_name() == "Allocated to":
                    EObject.delete_e_object(rel)

when running the script I get a weird behaviour.
If there is only a relation or there are three or more, I get the following Java exception, while if two relations are associated to the requirement, only the first one is deleted.

java.util.ConcurrentModificationException
	at org.eclipse.emf.common.util.AbstractEList$EIterator.checkModCount(AbstractEList.java:751)
	at org.eclipse.emf.common.util.AbstractEList$EIterator.doNext(AbstractEList.java:699)
	at org.eclipse.emf.common.util.AbstractEList$EIterator.next(AbstractEList.java:685)
	at org.eclipse.python4capella.modules.JavaModule.iteratorNext(JavaModule.java:46)
	at jdk.internal.reflect.GeneratedMethodAccessor73.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:244)
	at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:357)
	at py4j.Gateway.invoke(Gateway.java:282)
	at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
	at py4j.commands.CallCommand.execute(CallCommand.java:79)
	at py4j.ClientServerConnection.sendCommand(ClientServerConnection.java:244)
	at py4j.CallbackClient.sendCommand(CallbackClient.java:384)
	at py4j.CallbackClient.sendCommand(CallbackClient.java:356)
	at py4j.reflection.PythonProxyHandler.invoke(PythonProxyHandler.java:106)
	at jdk.proxy16/jdk.proxy16.$Proxy42.executeScript(Unknown Source)
	at org.eclipse.ease.lang.python.py4j.internal.Py4jScriptEngine.internalExecute(Py4jScriptEngine.java:240)
	at org.eclipse.ease.lang.python.py4j.internal.Py4jScriptEngine.execute(Py4jScriptEngine.java:227)
	at org.eclipse.ease.AbstractScriptEngine.inject(AbstractScriptEngine.java:189)
	at org.eclipse.ease.AbstractScriptEngine.run(AbstractScriptEngine.java:242)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)

Solved!

The issue is related a concurrent access to an EMF list.

A frozen copy of the list is needed, and it is implemented by the following function:

def snapshot(e_list):
    copy = []
    for it in e_list:
        copy.append(it)
    return copy

Then the loop on the requirements is modified as follows:

    for req in m.get_owned_requirements():
        logging.info("Reassigning requirement %s", req.get_attribute('IE PUID').get_value())

        rels = req.get_owned_relations()
        relsFrozen = snapshot(rels)
        for rel in relsFrozen:
                if rel.get_relation_type()[0].get_long_name() == "Allocated to":
                    rels.remove(rel)
       

I hope that it could help.

1 Like