Finding the right nsURI (& Debugging Optimal method)

Hello,

To find a missing nsURI, usually we use this query:

self.eClass().ePackage.nsURI

However i found myself wondering about one particular nsURI that could not be identified through this method (as far as i know), i am wondering what is the best method to debug my M2DOC queries in general. The following debug method is explained:


Goal : [Get access to requirements (using the Capella Requirement addons)]
First Try :

aql:self.eAllContents(Requirements::Requirement)
selection.eAllContents(Requirements::Requirement)

No result, this message appears:

INFO: Empty collection: Nothing will be left after calling eAllContents: EClassifier=SystemEngineering can’t contain EClassifierLiteral=Requirement direclty or indirectly (9, 49)
(Btw there is a typo in "direclty" in M2DOC 3.1.0)

Google research + forum research, i found this :
https: //github. com/ ObeoNetwork/M2Doc/issues/276 (2018 topic)
The answers would not help for my specific need.


Let’s try to check the interpreter again:
selection.eAllContents(Requirements::Requirement)
Does work find, but only if it’s called from a CapellaModule Eclass.

One solution would be to get the CapellaModule from the self variable and then call the requirements.

We can check the tree /structure of our project to get helped:
image
We want “test Reqq”.
We can ASSUME that it is under the architecture

First method to get into it would be:

First method:

selection.containedLogicalArchitectures.ownedRequirementPkgs.eAllContents()

And analyse the results.

Except the interpreter would not work correctly here, it would not accept “eAllContents()” or “eContents()”, it accepts “eClass()” somehow though. No error message for eContents() by the way.

Let’s try another method:

selection.eAllContents(CapellaRequirements::CapellaModule).eAllContents(Requirements::Requirement)

Still not working. Same previous message + 1 error message.


Let’s keep looking, the researches led me to 2 paths:

  • https:// forum. mbse-capella. org/t/error-eclassifier-requirement-is-not-registred-in-the-current-environment/4784

in this topic, a problem of nsURI is mentioned. Fair enough, using the method mentioned at the beginning of this topic, i was able to find 2 missing nsURIs:
1- htttp://www.polarsys.org/kitalpha/requirements
2- htttp://www.polarsys.org/capella/requirements

my query is still not working.

  • The problem might be related to types or supertypes and all the EMF eclipse hidden structures? I could experiment with : “oclAsType()”, some experiments:

selection.eContents(capellacore::NamedElement)->at(3).eContents()->select(a|a.oclAsType(capellacore::NamedElement).name = ‘Requirements’)

selection.eContents(capellacore::NamedElement)->at(3).eContents()->select(a|a.oclAsType(capellacore::NamedElement).name = ‘CapellaModule’)

selection.eContents(capellacore::NamedElement)->at(3).eContents()->select(a|a.oclAsType(capellacore::NamedElement).eClass().name = ‘CapellaRequirements::CapellaModule’)

selection.eContents(capellacore::NamedElement)->at(3).eContents()->select(a|a.oclAsType(capellacore::NamedElement).eClass().name = ‘Requirements::Requirement’)

selection.eContents(capellacore::NamedElement)->at(3).eContents()->select(a|a.oclAsType(capellacore::NamedElement) = ‘Requirements::Requirement’)

selection.eContents(capellacore::NamedElement)->at(3).eContents()->select(a|a.oclAsType(capellacore::NamedElement) = ‘CapellaRequirements::CapellaModule’)

These are probably all wrong, and most importantly useless because any additional “capellacore::NamedElement” experimentations i did, would not include the requirements.
(by the way: at(3) is the Logical Arch we see on the image)

The message I got from the intepreter was however very interesting:

WARNING: EClassifier=ElementExtension is not registered in the current environment (76, 77)

This would finally lead me to this topic :
Problems accessing fields (2020 topic)

Finally this nsURI is mentioned : “http://www.polarsys.org/kitalpha/emde/1.0.0
This was the missing one. My queries work ! (Accessing to CapellaModule then access to Requirements::Requirement).

My question(s):

  1. No Matter how I would have used “self.eClass().ePackage.nsURI” tool, I would have never guessed the missing “emde/1.0.0” nsRUI, Was there any method to find it? I am genuinly curious because this could save me some time in the futur.

  2. Why would :

selection.eAllContents(Requirements::Requirement)

not work directly? (selection is pointed at the usual self element)

Why do I have to access to CapellaModule FIRST, then be able to call eAllContents(Requirements::Requirement).
The image attached to this post, shows clearly that Requirements elements are located on the tree at the end (UNDER the tree).
The self parameter or selection (pointed at the the system engineering element), is clearly located ABOVE it. Would not “eAllContents(Requirements::Requirement)” be supposedly enough to call the requirements elements? If it’s possible to “call” the requirements without entering the CapellaModule shown in the image. If so, how could that be done?

  1. Let’s go back to oclAsType() function, you said in the a previous post that :

EStructuralFeature (EAttribute and EReference) have a type. This type is used by AQL after the navigation of this segment of the expression (in your example source) to know what can be called next. In some cases this type can be more generic (a super type) than the type of the element you expect, in that case you can add a cast with the oclAsType() service. It will tell AQL at this point I have a more specific type and access EStructuralFeature or services defined on this specific type. If at runtime you have an element of a more generic type it will produce a runtime exception

From my understanding, in Capella/eclipse the “layers” of classes are not limited to 2 (Eclipse model + Capella Metamodel) ? This means there are types/superTypes and maybe even more.

A simple request from me, if that is possible, could you or someone share some sort of diagram/image / paint to show how the SuperClass, class and capella element interact? Sorry this might seem as a ridiculous request for someone who is expert on EMF and Capella Ecore…


Another example with oclAsType(capellacore::NamedElement). Actually, this can be used to call the PARENT of a function, and check on of its paremeters.

m:for FunctionAnaly| …
m:let FParent = FunctionAnaly.eContainer()

In this particular case, the parent’s parameter of that function, can only be extracted with oclAsType(capellacore::NamedElement),

Does that mean, we are “selecting” from different types of classes returned from “eContainer()” only those that are Capella related. Does it mean that eContainer() returns many classes somehow?

(Finally: the method I used to debug, using several tools in hand + google /forum research, do you think there is a better optimal solution for debugging here in M2DOC? Any other tips? Thanks)

Thank you, I opened a bug in AQL fro the typo:

One way to list all needed nsURIs could be something like:

root.eAllContents()->collect(e | e.eClass()->asOrderedSet() + e.eClass().eAllSuperTypes)->asOrderedSet().ePackage.nsURI->sortedBy(n | n)

That will give you all the nsURIs used bellow the given root element. It works by collecting all EClasses and all their super types.

Yes the extension system used by addons (including the requirement addon) is defined in the http://www.polarsys.org/kitalpha/emde/1.0.0 metamodel. It contains the containment EReference ownedExtensions that can be used to navigate to extensions applied on a given CapellaElement.

The eAllContents() with a filter type relies on registered nsURIs (metamodels) to prune the model tree. If it finds no way to access elements of the given type you will have the information message you showed above. In your case some nsURIs are missing.

The eAllContents() service with a filter works on the CapellaModule because all containment EReferences are defined inside a metamodels you already have imported in order to reach elements of type Requirement.

Yes you can have a depth of more than two in the type hierarchy. That is a request that a lot of people working with Capella have. You can use EcoreTools to create such a diagram. As far as I know Capella doesn’t provide those diagrams.

The eContainer() service retuurns an EObject which is the most generic type of element in EMF. You can use a type as parameter to get the first element of the given type in the containment references. And the result will be typed as the given type:

....eContainer(capellacore::NamedElement).name

To write M2Doc templates, I use the content assist of the M2Doc interpreter view. When I don’t find some EStructuralFeatures from the Capella metamodel, I use the eClass().eAllStructuralFeatures to list all available features and see if one could be helpful. Then I check the result, after some time the Capella metamodel starts to be more familiar. I’m also already familiar with most of AQL and M2Doc services so it helps.

1 Like