Approaching M2DOC - Philosophy/ available features, options

Hello,
I have been talking to a friend who used M2DOC, and he said he approached M2DOC with a trial and error method.
I tried this method and I still find myself asking many questions, I would rather MASTER M2DOC than “trying and experimenting and being stuck sometimes without knowing what is the error”.

So I would like to put on the table all I have found about M2DOC in my short time of research, and I would like you to give me a feedback on what kind of inputs/documentations i might be missing.

To approach M2DOC, i found i should:

  1. Learn basic Acceleo, using the available documentation on eclipse website.
  2. Check the xml codes of “.capella” files on my project and search for the attributes “xsi:type” of the xml tags. Then make use of the last part of the value of that attribut, example
    ( xsi:type=“org.polarsys.capella.core.data.fa:ComponentPort”), the useful part here is : “fa:ComponentPort” --> Which becomes “fa::ComponentPort” is AQL/sirius.
  3. Define a very high level variable (named self) Type such as “capellamodeller::SystemEngineering”, in order to be able to summon any item located on a lower level of the hiearchy of items, using this : “aql:self.eAllContents(Insert what i found on point 2)” this becomes --> “m:self.eAllContents(la::LogicalComponent)” (Supposedly). The strategy here is to follow the example shown on the Acceleo docu:
    https://www.eclipse.org/acceleo/documentation/aql.html
    The " eAllContents()" example but instead of “travel agency” as a top class, i have “capellamodeller::SystemEngineering”.
  4. So as mentioned in point 3, all I need to call for an item from my project is to insert it inside “m:self.eAllContents(item_xsi_type)”
  5. Furthermore, check all the “services” available on the nightly M2DOC documentation, to find functions as “isRepresentationDescriptionName()” and such.
    Here? https:// github. com / ObeoNetwork/M2Doc/tree/master/tests
    And Here? https ://www.m2doc.org/ref-doc/nightly/m2doc_service_paginationservices.html
  6. Finally, one last option is to use the example given through the Flight fun project, check the template and the generated document and compare (trial and fail).
  7. Test that on my proper project.

But i am hitting some walls, i am noticing.

First of all:
A) I see that this code : {m:self.eAllContents(la::LogicalComponent)->size()}
would work on the sirius interpreter and provide me with the number of logical components (2 for a very simplistic testing project)
yet the Generated product would produce an error:
{m:self.eAllContents(la::LogicalComponent)->size()}<—Expression “self.eAllContents(la::LogicalComponent)->size()” is invalid: invalid type literal la::LogicalComponent

B) Also when i read the comments from a previous post (post i mentioned on one of my posts) a person had a problem using this :
“self.eAllContents(fa::ComponentExchange).source”
he had to add “oclAsType()” instead, to solve it:
“ce.source.oclAsType(fa::ComponentPort).orientation”
( AQL query works on Sirius interpreter, returns error on M2DOC - Document Generation - Eclipse Capella Forum (mbse-capella.org) - last post)

Something i would have never thought.

C) I can’t find the the xmi:type for NOTES/Notations.
image
indeed, they are not defined in the .capella file, but rather in the .aird file which contains different set of attributes and tags.

How can i get their content (“Text i would like to extract” and “Text2 I would like to extract aswell”) using aql? I mean M2DOC?

D) Also, i can see all the services and nsURI available on my template edit options, but I can’t seem to be able to identify the precise role of each one of them, i have seen some descriptions of services on the nightly docu for M2DOC but it does it is not necessarily associated with the items shown the window. I would rather identify the role of each nsURI/service.


Finally, i must explain that I have never used Capella Studio, and i have No idea what are the exact classes and objects of Capella modelisation, will that be a problem that i should attend to in order to hope to achieve mastery in M2DOC?
Also, is there some Classes diagram for Capella classes? (One that describes all classes in one big diagram).


What am I missing?

Thanks

Hi,

Thanks for your feedback.

In addition to M2doc as such, we try to do our best to document and provide examples so that people can discover M2Doc and use it by themselves. This is why we created the ‘get started’ section and specifically the page ‘use with Capella’.
This is also why we frequently reply on the forums.
All of this without counterparty.

However, I fully agree that discovering M2doc by trial and error can be tedious. Mainly because it requires many pre-requisites ( proficiency in AQL [which is not exactly Acceleo], knowledge of the Capella metamodel, EMF and Eclipse in general, etc).

And so, if your objective is to master M2Doc, it is also possible to consider either :

Feel free to contact me for details.

BR

Samuel

1 Like

I will make sure to contact you.
It appears to me there are 2 M2DOC courses and available only during certains dates on a calender (not on-demand).

Yes as for the “getstarted” section, it is what i refered to as “M2DOC docu”

All of this without counterparty

Yes I noticed.

Mainly because it requires many pre-requisites

Does that M2DOC training course require said pre-requisites?


All of this without counterparty

Could you inform me on how would it be possible to extract the contents of the following yellow notes ?
image
Info : My variable is “self → capellamodeller::SystemEngineering”

( proficiency in AQL [which is not exactly Acceleo], knowledge of the Capella metamodel, EMF and Eclipse in general, etc).

Supposedly, I would have the time to attack every one of these pre requisites. What kind of exercices / tutorials would you recommand for each of one?
I was thinking :

  • The Acceleo geting started on ECLIPSE (without capella)
  • Making a plugin in Capella studio.

    What else?

Thanks for your feedback.

No problem.

Thanks

Hello,

  1. Yes it a good starting point to have an idea on how AQL works and the basic syntax. The difference between . (for scalar or iterates over each element of a collection) and -> (applies on a collection). And may be the syntax of services that take a lambda as parameter like select(e | e.name = ‘’). You can also read the M2Doc documentation and find the same information for the M2Doc language.

After that I would recommend using the M2Doc interpreter and use the content assist with CTRL+SPACE. It will help you find services or types you can apply at a given point of your expression.

  1. To find the type of an element, you can select it in Capella and use the following:

If you are selecting it from a diagram or a table representation:

selection.target.eClass().name

Otherwise or if you want the type of a representation element:

selection.eClass().name

AQL and M2Doc are based on EMF and representation elements are also EObject (root type for EMF model elements). The representation element reference the semantic element (from Capella) through the target EReference. Then we use a reflective service to get the EClass of the element which define its type. Then we get its name that can be used later in the AQL expression. The eClass() call allows you to navigate from the model to its metamodel which defines the structure of the model. You can also use other calls that starts with “e” after it to navigate the metamodel, for instance:

…eClass().eAllStructuralFeatures
…eClass().eAllSuperTypes

  1. Yes that is a generic way of collecting elements of a given type without relying on the model structure (metamodel).

  2. Yes

  3. You could also use the content assist in the M2Doc interpreter with CTRL+SPACE all AQL and M2Doc services are documented, and you should be able to see the documentation with the content assist.

  4. The In-Flight Entertainment system project is meant to be used as a starting point to see what can be done with Capella and M2Doc. And provided templates try to demonstrate useful example in the context of MBSE and Capella.

So far You only missed the content assist I guess and a bit of explanation on how models conform to a metamodel that can be requested as well with AQL.

A) you need to import the “la” EPackage (metamodel) nsURI. If you want to get the needed EPackage nsURI from an element you can use:

   ....eClass().ePackage.nsURI

You can then add the nsURI to your template with the template properties wizard. AQL needs a list of used metamodels to work with. This allows for optimizations like pruning branches of the model in the filtered eAllContents() service. That also help providing completion in the content assist.

B) 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.

To check on this example you can select a ComponentExchange on a diagram and use:

selection.target.eClass().eAllStructuralFeatures->select(f | f.name = 'source').eType

This will return the EClass InformationsExchanger. And InformationsExchanger is a super type of ComponentPort:

fa::ComponentPort.eAllSuperTypes.name->includes('InformationsExchanger')

C) The semantic model (Capella) and the representation model (Sirius) are two distinct models in the way they don’t include each other. Only the representation model reference the semantic model. The representation model is serialized in the .aird file and the semantic model in the case of Capella is serialized in the .capella file. So to access notes, the first step will be to get a diagram representation with one of the Sirius service:

'[LAB] IFE System - All Components, CEs'.representationByName()

Here I’m using the simplest way to do it, it’s not the best way since if the representation is renamed it will break this expression.

If you select a note and use the expression in the M2Doc interpreter:

selection

You will have an error telling you Shape is not registered as a type. So the EClass name is Shape, and with the Sirius interpreter you can use:

aql:self.eClass().ePackage.nsURI

You can also check the serialized .aird file to find this information. You can add http://www.eclipse.org/gmf/runtime/1.0.3/notation to your template and refresh the M2Doc interpreter view. GMF stands for Graphical Modeling Framework and is used by Sirius.

You can then use the content assist to get interesting features like the type, description, sourceEdges, and targetEdges.

D) nsURIs are related to each metamodels you are using: Capella, Sirius, GMF, … The only rule is you can find nsURIs at the top of XMI files (.capella, .aird, …).

For services from AQL and M2Doc you will have access to the documentation in the content assist. I think someone made a class diagram of the Capella metamodel but I’m not sure where you can find it. You can use Ecore Tools to make your own.

I hope it helps. Obeo is also giving training as mentioned by Samuel.

1 Like

Thanks a lot for this answer. I will probably answer you in the week end or next week.
I have one quick observation, then i will read your answer again, work furthermore and come back with other responses:

This link does not work. Does it work for you? I noticed i met non working links when surfing through the web while searching for Acceleo packages, among other things.

image

It’s the nsURI for GMF, you should add it to your template.

1 Like

Hello again,
I read this part almost everyday i am working on M2DOC. i try to use these features/tools, every day in order to try to master M2DOC.
Until today, I always associated “M2DOC intepreter” codes that work on the iterpreter but would not work in the template as bieng a problem of unavailability of a service.
It is not always the case it seems.

I am trying to associate an operational capability to its diagram (Operational Capabilities Blank).

If you take the M2DOC interpreter and and select an Operational Calability and write :

selection.eContainer().asImage()

The diagram would show up under the code on the M2DOC interpreter.
However, that will never work on the template.

  1. First Try:
    M2DOC interpreter:
    “selection.asImage()”
    Template:

m:let X = self.eAllContents(oa::OperationalCapability)
m:for Y|X
Y <— Couldn’t find the ‘asImage(EClassifier=OperationalCapability)’ service.asImage()

  1. Second try, this one is similar to the M2DOC interpreter code:
    M2DOC interpreter code : “selection.eContainer().asImage()”
    Template error:

m:let X = self.eAllContents(oa::OperationalCapability)
m:for Y|X
Y.eContainer() <— Couldn’t find the ‘asImage(EClassifier=OperationalCapabilityPkg)’ service Couldn’t find the ‘asImage(EClassifier=ModelElement)’ service Couldn’t find the ‘asImage(EClassifier=GenericPkg)’ service Couldn’t find the ‘asImage(EClassifier=EAnnotation)’ service Couldn’t find the ‘asImage(EClassifier=DAnalysisCustomData)’ service Couldn’t find the ‘asImage(EClassifier=ToolGroupInstance)’ service Couldn’t find the ‘asImage(EClassifier=AnnotationEntry)’ service Couldn’t find the ‘asImage(EClassifier=TableDescription)’ service.asImage()

Why does this work in the M2DOC intepreter and not here?

  1. Third Try:
    M2DOC interpreter: “selection.eContainer().representationByDescriptionName(‘Operational Capabilities Blank’).asImage()”
    Template:

m:let X = self.eAllContents(oa::OperationalCapability)
m:for Y|X
Y.eContainer().representationByDescriptionName(‘Operational Capabilities Blank’).asImage().setWidth(250)

This one works! But it shows ALL the OCBs diagrams.

I am trying to show only the diagram related to the operational entity (Y) I have in hand.

I thought it could be a service/ nsRUI thing, but :

selection.eContainer().eClass().ePackage.nsURI

would display a service i already have (http://www.eclipse.org/sirius/diagram/1.1.0).

Why does my code not work?
And Is there another way to do it? Meaning : Extract a diagram for an element which has been identified under a “for” loop, such as my Y variable (which is, here, attached to an Operational Capability). Or another way to tackle this maybe differently?

As I said, I reread what you have wrote everytime I can.
I tried to use this 2 tools :
…eClass().eAllStructuralFeatures
…eClass().eAllSuperTypes

When taking the Operational Capability, the Stuctural Features are:

uid
target
name
semanticElements
visible
tooltipText
parentLayers
decorations
transientDecorations
diagramElementMapping
graphicalFilters
ownedBorderedNodes
arrangeConstraints
outgoingEdges
incomingEdges
width
height
ownedStyle
labelPosition
resizeKind
originalStyle
actualMapping
candidatesMapping

and the target:

ownedExtensions
id
sid
constraints
ownedConstraints
ownedMigratedElements
name
incomingTraces
outgoingTraces
visibleInDoc
visibleInLM
summary
description
review
ownedPropertyValues
ownedEnumerationPropertyTypes
appliedPropertyValues
ownedPropertyValueGroups
appliedPropertyValueGroups
status
features
appliedRequirements
ownedTraces
containedGenericTraces
containedRequirementsTraces
namingRules
ownedPropertyValuePkgs
involvedInvolvements
ownedFunctionalChains
preCondition
postCondition
ownedScenarios
incomingCapabilityAllocation
outgoingCapabilityAllocation
extends
extending
abstractCapabilityExtensionPoints
superGeneralizations
subGeneralizations
includes
including
super
sub
includedAbstractCapabilities
includingAbstractCapabilities
extendedAbstractCapabilities
extendingAbstractCapabilities
ownedFunctionalChainAbstractCapabilityInvolvements
ownedAbstractFunctionAbstractCapabilityInvolvements
availableInStates
ownedAbstractCapabilityRealizations
involvedAbstractFunctions
involvedFunctionalChains
compliances
configurations
ownedEntityOperationalCapabilityInvolvements
realizingCapabilities
involvedEntities

The super types are:

IdentifiedElement
DMappingBased
DStylizable
DRefreshable
DSemanticDecorator
DRepresentationElement
DDiagramElement
AbstractDNode
EdgeTarget
DragAndDropTarget

The target:

Element
ExtensibleElement
ModelElement
AbstractNamedElement
TraceableElement
PublishableElement
CapellaElement
NamedElement
Namespace
Structure
InvolverElement
AbstractFunctionalChainContainer
AbstractCapability

When taking the parent (eContainer), the structural features are:

uid
eAnnotations
ownedRepresentationElements
representationElements
ownedAnnotationEntries
uiState
name
documentation
ownedDiagramElements
diagramElements
description
edges
nodes
nodeListElements
containers
currentConcern
activatedFilters
activatedTransientLayers
allFilters
activatedRules
activateBehaviors
filterVariableHistory
activatedLayers
synchronized
hiddenElements
isInLayoutingMode
isInShowingMode
headerHeight
target

The target:

ownedExtensions
id
sid
constraints
ownedConstraints
ownedMigratedElements
name
incomingTraces
outgoingTraces
visibleInDoc
visibleInLM
summary
description
review
ownedPropertyValues
ownedEnumerationPropertyTypes
appliedPropertyValues
ownedPropertyValueGroups
appliedPropertyValueGroups
status
features
appliedRequirements
ownedTraces
containedGenericTraces
containedRequirementsTraces
namingRules
ownedPropertyValuePkgs
ownedOperationalCapabilities
ownedOperationalCapabilityPkgs
ownedCapabilityConfigurations
ownedConceptCompliances

As for the super types:

IdentifiedElement
DModelElement
DRefreshable
DRepresentation
DragAndDropTarget
DDiagram
DSemanticDecorator

The target:

Element
ExtensibleElement
ModelElement
AbstractNamedElement
TraceableElement
PublishableElement
CapellaElement
NamedElement
Namespace
Structure
AbstractCapabilityPkg

I was wondering, am I supposed to play with this elements in order to achieve my goal here ? Use every bit of these elements to find which diagram contains my operational capability, then tell M2DOC to print only that one Diagram i want?

  1. You probably selected the OperationalCapability from a diagram meaning you have selected a DRepresentationElement representing the OperationalCapability, not the OperationalCapability itself.
    You can access the OperationalCapability using:

    selection.target
    

The features you show in the first block are DrepresentationElement EClass features. The target block shows the features of the OperationalCapability EClass.

The asImage() service ca be applied on a DRepresentation or a String (to load an image using an URI).

  1. That the same problem, your OperationalCapability is contained in a OperationalCapabilityPkg, which is expected.

  2. You are almost there, you probably don’t need the eContainer() part since Y is already the OperationalCapability you are looking for:

    Y.representationByDescriptionName(‘Operational Capabilities Blank’).asImage().setWidth(250)
    

You can also list all diagrams showing a given element:

diagram::DSemanticDiagram.allInstances()->select(d | d.representationElements->select(re | if re.oclIsKindOf(diagram::DDiagramElement) then re.visible else true endif)->including(d).target->includes(Y))

Then you can select the one you are interested in.

1 Like
  1. This code:

{m: Y.representationByDescriptionName(‘Operational Capabilities Blank’).asImage().setWidth(250) }

Shows nothing.

  • If i understand well the function ‘representationByDescriptionName()’, returns the “DrepresentationElement” that i was pointing out with M2DOC interpreter ? It’s the opposite of Target if I am not wrong. thanks
  1. And this one:

{m: Y.eContainer().representationByDescriptionName(‘Operational Capabilities Blank’).asImage().setWidth(250)}

Shows ALL OCB diagrams, even if the Operational Capability in hand (Y), is not part of the diagram.

  1. While your other suggestion:

{m: diagram::DSemanticDiagram.allInstances()->select(d | d.representationElements->select(re | if re.oclIsKindOf(diagram::DDiagramElement) then re.visible else true endif)->including(d).target->includes(Y)}

would produce this error message:

org.eclipse.sirius.diagram.business.internal.metamodel.spec.DSemanticDiagramSpec@3883cde (uid: _DuxxxxxxxxxxxxxxxxxUmzQ) (synchronized: true, isInLayoutingMode: false, isInShowingMode: false, headerHeight: 1)org.eclipse.sirius.diagram.business.internal.metamodel.spec.DSemanticDiagramSpec@38dc5f85 (uid: _jTLxxxxxxxxxxxxdIA) (synchronized: true, isInLayoutingMode: false, isInShowingMode: false, headerHeight: 1)

So if I am getting this right (assuming the green code would have worked), this is an image of almost everything to take in account to understand M2DOC fully ? Image below :


(I probably made some mistakes)
I honestly was impressed by the length of your last suggestion code, the one used to display all diagrams showing a given element. It is impressive and overwhelwing.

  1. So, is this representation right?

To access to the Eclipse element, through the Template, the only way is to use the Service. And only a handflul of them can achieve this? (representationByDescriptionName, asImage,…)

Isn’t there an equivalent to “target” that always work? Such as “origine” or ReverserTarget.

Thanks

  1. The diagram you want to insert is not hold by the Y element. To know which element hold your diagram you need to select the background of the diagram an use:

    selection.target

Let call the resulting object X, you can then do:

X.representationByDescriptionName(‘Operational Capabilities Blank’).asImage().setWidth(250)
  1. This means that all your Operational Capabilities Blank diagrams are hold by the OperationalCapabilityPkg.

  2. This is not an error message but a list of DSemanticDiagram represented as a String. You can add a .name to get a list of readable names.

  3. Writing AQL queries need some practice but you will probably reuse the same logic at many places in your template. The main part of the query checks if the diagram element is visible so diagrams where the object is hidden will not be selected.

4/5) A diagram will use DRepesentationElement to represent semantic elements (in this case CapellaElement). You can go from the DRepesentationElement to the semantic element using the target EReference. In your template, you usually use semantic elements (from the Capella model), but you are not limited to them since DRepesentationElement are also EObjects, you can query them the same way with AQL. The M2Doc interpreter is configured the same way as the M2Doc is configured during generation. It can be done using the .genconf file. So there is no differences in the two modes.

The thing is when you select an element on the diagram, you will select the DRepesentationElement representing it on this diagram and not the semantic element (CapellaElement accessible via the target EReference). When you select an element from the project explorer you are selecting directly the semantic element (CapellaElement). It’s done this way to be able to represent one semantic element more than once on a diagram for instance.

I hope this explanation will help you.

There is a service to navigate a reserence in the oposite direction see the AQL documentation:

capellaElement.eInverse('target')

or

capellaElement.eInverse(viewpoint::DRepresentationElement)
1 Like

Hello,
This 2 calls usually work well after any “item.Eclass()”, the interpreter would usually show the Eclass() and its contents like this:

Notice the red cercle that let you unfold the eClass,

My question, what happens when:

The resulting eClass, cannot be “unfolded”? Even (eClass().eAllStructuralFeatures
…eClass().eAllSuperTypes) don’t work here.

How is it possible to access to “FontStyle” for example? Or “FillStyle”, “RoundedCornersStyle” in this example?

The aql expression is navigating in the diagram through nodes and annotationEntries.

Thanks a lot

I don’t know why the Sirius interpreter has de different behavior since you have an EClass in both cases. Maybe the Sirius interpreter limit access to the GMF medamodel for some reason.
You can maybe try the M2Doc interpreter view and see if you can call eAllStructuralFeatures on it. You will need to add the GMF notation model nsURI to your template to try this.

I wonder what is this reason.
__
Anyway, first thing, thank you for the reminder for nsRUI. I got too used to the sirius interpreter that I had forgotten about the “selection” variable replacing “aql:self”.

So I went ahead and tried what you mentioned:
Here is the class:

The eAll… calls do indeed work in this intrepreter:

A casting was needed to further the analysis by the way,

Thank you.
__
Feedback: I don’t know if the latest versions of M2DOC interpreters got a “CTRL+Z/W” option, but it really needs it!
Second item: selecting another tab in the tab holding window (the one with “console”, “properties”) will make M2DOC lose it’s “selection”, that does not happen with the sirius interpreter. (M2DOC 3.0.1)

OK my bad, the reason is ShapeStyle doesn’t have any EStructuralFeature. That’s why you can’t unfold it. All its EStructuralFeature comes from super EClass.

The interpreter doesn’t support “CTRL+Z/W”.

I think it might be possible to select some text for instance and use it as the value of the selection variable. I use the current selection returned by the Eclipse platform.

1 Like

Hey Yvan,
Sorry I did not understand this part, what did you mean?

I mean I didn’t restrict the update of the selection variable in the M2Doc interpreter view, where the Sirius interpreter probable only update the value if the current selection is an EObject.
I checked the text selection is not supported…

image

I would expect ‘SymbolicName’ as the result of the evaluation.

1 Like