How to set type for ExchangeItemElement

Hello Python4Capella
I need to set ExchangeItemElement type as a set of self-defined Numeric Type, such as int8/float64. These numeric types are defined in a “DataType” capella library and referenced in this project.
Now P4C provides get_type(). Is there any way to set_type for ExchangeItemElement? If needed, we could duplicate those data types into this project if the DataType library gets in the way.

You need to set the abstract type:

myDataType = ...
myExchangeItemElement.setAbstractType(myDataType.get_java_object())

Thanks. It makes sense.
I am trying to get numeric type under a reference library
for lib in model.get_referenced_libraries():

File “workspace://Python4Capella/WIP.py”, line 48, in
# Python 3.*
File “workspace://Python4Capella/simplified_api/capella.py”, line 55, in get_referenced_libraries
def _pyease_patch_builtins(name, value):
File “workspace://Python4Capella/java_api/Capella_API.py”, line 60, in get_libraries
:param name: Name of the builtin
File “workspace://Python4Capella/simplified_api/capella.py”, line 78, in open
string_types=_pyease_string_types,
NameError: name ‘unicode’ is not defined

The unicode type is a Python 2.x type, it has been replaced by the str type in Pyhton 3.x. You can remove this part of the test in capella.py line 78. At some point I should remove it.

I edited capella.py line 78 as
def open(self, obj: Any):
“”"
Parameters: path: String
status: KO
“”"
# obj can be a path to the .aird file or an EObject
if isinstance(obj, str): # remove or isinstance(obj,unicode):
if CapellaPlatform.getWorkspaceFile(obj) is None:
raise AttributeError("the .aird file doesn’t exist: " + obj)
self.session = Sirius.load_session(obj)
elif isinstance(obj, EObject):
self.session = Sirius.get_session(obj.get_java_object())
else:
raise AttributeError(“You can pass a path to the .aird file or an EObject.”)

However, the get_referenced_libraries() does not finish itself at Capella_API.py

def get_libraries(system_engineering):
res =

if system_engineering is not None:
    lib_cls = getattr(sys.modules["__main__"], "CapellaLibrary")
    for value in getLibraries(system_engineering.get_java_object()):
        lib = lib_cls()
        lib.open(value) # raises error below

The value is an object of SystemEngineering[TRANSIENT], and open function raises AttributeError(“You can pass a path to the .aird file or an EObject.”)

I think a wrapping to the Python API is missing. I can’t test this now but the following code should help:

def get_libraries(system_engineering):
    """Gets the list of libraries for the given system engineering"""
    res = []
    
    if system_engineering is not None:
        lib_cls = getattr(sys.modules["__main__"], "CapellaLibrary")
        e_object_class = getattr(sys.modules["__main__"], "EObject")
        for value in getLibraries(system_engineering.get_java_object()):
            lib = lib_cls()
            lib.open(e_object_class(value))
            res.append(lib)
        
    return res

Please let me know if it works so I can open an issue to fix that later.

I followed your code by replacing get_libraries.

I have a model with one library. But the main code as below prints out the LC of the model, rather than the library’ LC as expected.

for lib in model.get_referenced_libraries():
    lib_se = lib.get_system_engineering()
    for lc in lib_se.get_logical_architecture().get_logical_component_pkg().get_owned_logical_components():
        print(lc.get_name())

The CapellaLibrary reference a Java SystemEngineering… So as a workaround you can use:

lib_se = SystemEngineering(lib.get_java_object())

The ides in the code is to be able to use the library project like the main project. But the current code uses the main project.

I opened the following issue for more details. In short at the moment you won’t be able to extract diagrams from the library but you should be able to access semantic elements (CapellaElement).

SystemEngineering(lib.get_java_object()) threw out
AttributeError: ‘CapellaLibrary’ object has no attribute ‘get_java_object’

I tried to use CapellaLibrary existing method java_object() to replace get_jave_object(). It threw out
TypeError: ‘JavaObject’ object is not callable

I changed my answer and removed a part of it.

You also need to change the class CapellaLibrary to extends SystemEngineering:

class CapellaLibrary(CapellaModel):

should be:

class CapellaLibrary(SystemEngineering):

org.eclipse.ease.ScriptExecutionException: Traceback (most recent call last):
File “workspace://Python4Capella/[WIP].py”, line 114, in
if isinstance(value, dict_types):
File “workspace://Python4Capella/simplified_api/capella.py”, line 55, in get_referenced_libraries
def _pyease_patch_builtins(name, value):
File “workspace://Python4Capella/java_api/Capella_API.py”, line 75, in get_libraries
value,
AttributeError: ‘CapellaLibrary’ object has no attribute ‘open’

def get_libraries(system_engineering):
    """Gets the list of libraries for the given system engineering"""
    res = []

    if system_engineering is not None:
        lib_cls = getattr(sys.modules["__main__"], "CapellaLibrary")
        e_object_class = getattr(sys.modules["__main__"], "EObject")
        for value in getLibraries(system_engineering.get_java_object()):
            lib = lib_cls()
            lib.open(e_object_class(value)) # Error happens here
            res.append(lib)

Yes you need to remove this statement. It’s not needed any more.

Now the error threw at

lib_se = SystemEngineering(lib.get_java_object())

org.eclipse.ease.ScriptExecutionException: Traceback (most recent call last):
File “workspace://Python4Capella/[WIP].py”, line 129, in
for converter in gw.converters:
AttributeError: ‘CapellaLibrary’ object has no attribute ‘get_java_object’

For lib, following features are available
[‘class’, ‘delattr’, ‘dict’, ‘dir’, ‘doc’, ‘eq’, ‘format’, ‘ge’, ‘getattribute’, ‘gt’, ‘hash’, ‘init’, ‘init_subclass’, ‘le’, ‘lt’, ‘module’, ‘ne’, ‘new’, ‘reduce’, ‘reduce_ex’, ‘repr’, ‘setattr’, ‘sizeof’, ‘str’, ‘subclasshook’, ‘weakref’, ‘e_class’, ‘java_object’]

An indirect removal of open statement may ignore the value, which is the loop iterator.
for value in getLibraries(system_engineering.get_java_object()):
lib = lib_cls()
# remove lib.open(e_object_class(value)) # Error happens here
res.append(lib)

It should if CapellaLibrary extends SystemEngineering:

class CapellaLibrary(SystemEngineering):

After that CapellaLibrary is a SystemEngineering and your code should look like this:

for lib in model.get_referenced_libraries():
    for lc in lib.get_logical_architecture().get_logical_component_pkg().get_owned_logical_components():
        print(lc.get_name())

I did not get what you mean. A direct remove might ignore the value from getLibraries(). I wonder how to introduce value into lib, which will be then appended to res.

I’ll try to recap everything here:

first change the extends in capella.py:

class CapellaLibrary(CapellaModel):

should be:

class CapellaLibrary(SystemEngineering):

Then change the Capella_API.py (I missed a step here):

def get_libraries(system_engineering):
    """Gets the list of libraries for the given system engineering"""
    res = []
    
    if system_engineering is not None:
        lib_cls = getattr(sys.modules["__main__"], "CapellaLibrary")
        for value in getLibraries(system_engineering.get_java_object()):
            lib = lib_cls(value)
            res.append(lib)
        
    return res

Then your code:

for lib in model.get_referenced_libraries():
    for lc in lib.get_logical_architecture().get_logical_component_pkg().get_owned_logical_components():
        print(lc.get_name())

It should be good after I changed

lib_cls = getattr(sys.modules[“main”], “CapellaLibrary”)

to

lib_cls = getattr(sys.modules[“main”], “SystemEngineering”)

Yes that’s an other way to do it. But you will not be able to distinguish a CapellaLibrary form a SystemEngineering later. But that’s probably not an issue.

I did it, because, if not, it threw out
AttributeError: ‘CapellaLibrary’ object has no attribute ‘get_all_contents_by_type’
I was weird to get such error since get_all_contents_by_type is method of base class JavaObject/EObject/CapellaElement/PropertyValuePkgContainer/SystemEngineering/CapellaLibrary

Meanwhile, as you instructed, after change to lib_cls = getattr(sys.modules[“main ”], “SystemEngineering”)
Sirius_API get_system_engineering() performed abnormally as it returns a random CapellaLibrary even though the session input was the main project in Team for Capella environment

@staticmethod
def get_system_engineering(session):
return getEngineering(session)

1 Like