How to obtain he "target" of a DNode element using P4C? (get_target() not working properly)

Hello,
I have been using:
elem = CapellaElement(CapellaPlatform.getFirstSelectedElement())
to select elements from a diagram.
The problem is that when the element is selected directly in the project explorer, everything works fine, but when the item is selected from a diagram then I would obtain a graphical element/class from Sirius (such as DNode… etc)
Let’s take the examples of both instances for this code:

elem = CapellaElement(CapellaPlatform.getFirstSelectedElement())
print(elem)
print(type(elem))
print(elem.get_id())
print("Test")
print("End of Script")

In both instances the type is “<main.CapellaElement object at 0x00000SomeNumberAdress>”, however their eclass is different (which is displayed only for the actual item, the node has no attribute/fonction for eclass).
When selectring from the diagram, then the item is a node, therefore our script code will naturally produce errors (You cannot get an “id” from a Node I believe, a Node is not an abstract element). The problem will be resolved if the graphical item is replaced with its targeted capella item.

When searching I found a function that gets the target for a diagram object. Click to expand:

class Diagram
class Diagram(JavaObject):
    """
    A generic Capella diagram
    """
    def __init__(self, java_object = None):
        """
        """
        if java_object is None:
            JavaObject.__init__(self, create_e_object("http://www.eclipse.org/sirius/1.1.0", "DRepresentationDescriptor"))
        elif isinstance(java_object, Diagram):
            JavaObject.__init__(self, java_object.get_java_object())
        else:
            JavaObject.__init__(self, java_object)
    def get_uid(self):
        """
        """
        return self.get_java_object().getUid()
    def set_uid(self, value):
        """
        """
        self.get_java_object().setUid(value)
    def get_name(self):
        """
        """
        return self.get_java_object().getName()
    def set_name(self, value):
        """
        """
        self.get_java_object().setName(value)
    def get_type(self):
        """
        """
        if self.get_java_object().getDescription() is None:
            return None
        else:
            return self.get_java_object().getDescription().getName()
    def get_package(self):
        """
        """
        if self.get_java_object().getTarget() is None:
            return None
        else:
            return self.get_java_object().getTarget().eClass().getEPackage().getName()
    def get_description(self):
        """
        """
        return self.get_java_object().getDocumentation()
    def set_description(self, value):
        """
        """
        self.get_java_object().setDocumentation(value)
    def get_status(self):
        """
        """
        value = Sirius.get_status(self.get_java_object())
        if value is None:
            return value
        else:
            return value.getName()
    def get_review(self):
        """
        """
        return Sirius.get_review(self.get_java_object())
    def get_visible_in_documentation(self):
        """
        """
        return Sirius.is_visible_in_documentation(self.get_java_object())
    def get_visible_for_traceability(self):
        """
        """
        return Sirius.is_visible_for_traceability(self.get_java_object())
    def get_synchronized(self):
        """
        """
        return Sirius.is_synchronized(self.get_java_object())
    def get_target(self):
        """
        """
        value =  self.get_java_object().getTarget()
        if value is None:
            return value
        else:
            e_object_class = getattr(sys.modules["__main__"], "EObject")
            specific_cls = e_object_class.get_class(value)
            return specific_cls(value)
    def get_represented_elements(self):
        """
        """
        res = []
        for element in Sirius.get_represented_elements(self.get_java_object()):
            e_object_class = getattr(sys.modules["__main__"], "EObject")
            specific_cls = e_object_class.get_class(element)
            if specific_cls is not None:
                res.append(specific_cls(element))
        return res
    def get_contextual_elements(self):
        """
        """
        return capella_query("org.polarsys.capella.core.semantic.queries.sirius.annotation.eoi.RepresentationToContextualElement", self)
    def get_elements_of_interest(self):
        """
        """
        return capella_query("org.polarsys.capella.core.semantic.queries.sirius.annotation.eoi.RepresentationToElement", self)
    def export_as_image(self, file_path):
        """
        status: KO
        """
        Sirius.export_image(self.get_java_object(), file_path)

I tried to apply it but failed, I wrote comments next to each line of code, to show the type of error I got:

elem = CapellaElement(CapellaPlatform.getFirstSelectedElement())
print(elem) #<__main__.CapellaElement object at 0x0000021B829CAD08>
print(elem.get_java_object()) # DNodeListEditPart( org.eclipse.gmf.runtime.notation.impl.NodeImp ...
#print(elem.get_java_object().target) #<py4j.java_gateway.JavaMember object at 0x0000021B829D0108>
#print(elem.get_java_object().get_target()) # Method get_target([]) does not exist
print(elem.get_target()) # AttributeError: 'CapellaElement' object has no attribute 'get_target'
print(elem.target) # AttributeError: 'CapellaElement' object has no attribute 'target'
print(type(elem))
print(elem.get_id())
print("Test")
print("End of Script")

I failed to obtain the targeted item using the following:

  • .get_java_object().target
  • .get_java_object().get_target()
  • .get_target()
  • .target

What am I missing? How can I obtain the actual target? Thank you.


Edit: I also tried the getTarget():

#print(elem.get_java_object().getTarget())
print(elem.getTarget())

AttributeError: ‘CapellaElement’ object has no attribute 'getTarget

Yes, the transition between the Python world and the Java world is a bit difficult. When you use CapellaElement() this creates a Python object and the parameter is a Java object. But nothing check that the Java object is compatible with the Python object or its class. That might be improved, I opened an issue:

You are almost there:

CapellaElement(CapellaPlatform.getFirstSelectedElement().getTarget())

Note: you can also restrict the element on which the menu will be visible in the header of your script (see this example).

1 Like

Hello Yvan, thank you. But no I don’t think i can restrict it this way (using (enableFor(org.polarsys.capella.core.data.capellacore.CapellaElement))) because the element I am targeting comes from an expansion (Req), and i was able to target it by changing the value inside enableFor(), by adding its “link” #org.polarsys… etc)

This code:

CapellaElement(CapellaPlatform.getFirstSelectedElement().getTarget())

Produces a massive error ahah! Look at this:

The selected element should be a diagram element.

It is selected directly from the diagram (look at the little black dots surrounding the element), this error (below) comes from it directly:

This is the script:

# Retrieve the Element from the current selection
elem = CapellaElement(CapellaPlatform.getFirstSelectedElement().getTarget())
print("a")

The character “a” is never printed. The error comes from the first line of code unfortunately

Edit: I actually get the exact same error message weither I select the item from the diagram or from the project exporer, strange no? Does it have anything to do with the fact that this element comes from an extension and is not native to Capella?

I missed that the selected element is a DNodeContainerEditPart and it reference a View from GMF annotation:

CapellaElement(CapellaPlatform.getFirstSelectedElement().getNotationView().getElement().getTarget())
1 Like

Perfect:)
I was able to to obtain the target from the diagram element.
Was “getNotationView()” and “getElement()” described anywhere? (SImplified metamodel word, or simplified api, or “capellaplatform”, or java api)

I noticed that most functions defined inside classes, were actually relying on other sub functions that are not listed. I am thinking about:

  • getTarget()
  • getVisibility()
    etc…

Those are Java method defined on DNodeContainerEditPart, DNode, and DSemanticDecorator. You can get the first Java class name with:

print(CapellaPlatform.getFirstSelectedElement())

If you have the Capella Java code, you can then find the DNode and so on.

Yes the simplified metamodel from Python4Capella delegates calls to the Java metamodel. Some times directly or with a bit of navigation. Results are then wrapped in JavaObject in the Python world. This way we keep a link between the Python object and the Java object. This link is then used to delegate further calls from Python to Java.

1 Like

Oh I see,
After searching, it seems this term “DNodeContainerEditPart”, can be found inside the plugin sirius.diargam.ui … I tried to investigate inside and Saw that that terme shows three times (in 3 classes).

  • I was not able to find the sirius.diagram.ui in the github link you shared (I found them instead inside a capella installation)
  • Even when I found them, I am no sure how to open the “.class” items, maybe “Eclipse Modeling tools”? Even that, I am so sure I would be able to open the .class items.

Notepad did not help much:

The Sirius source code. You might also be able to import deployed plugins into your workspace:

  • enable development capabilities in the Window > preferences menu. You can filter the tree using “capabilities”
  • right click in the project explorer and select import
  • select Plug-in Development / Plug-ins and Fragments
1 Like