Home » Modeling » Papyrus » Papyrus profiles with derived stereotype properties defined by same name operations(Papyrus profile issue)
Papyrus profiles with derived stereotype properties defined by same name operations [message #1835775] |
Fri, 11 December 2020 20:59  |
Eclipse User |
|
|
|
When I create a simple UML model with 2 classes A and B, with application of SysML.Requirement to both, then link them with an Abstraction relationship with Stereotype DeriveReqt applied, I can see in the profile variables of A and B the properties /derived and /derivedBy get updated with A and B respectively. However when I create a new custom profile and attempt to replicate this bahaviour, the equivalent /derived and /derivedBy Stereotype properties do not update with A and B.
I wasn't able to see any documentation on this topic, but I suspect some additional Java coding is needed to make this possible, am I right? However Papyrus seems to validate and check OCL code embedded in Constraints quite correctly, so I'm worried this should just work but I'm doing something wrong. Can you please review my examples "test", "test_profile" and "test_sysml"?
"test_sysml" works OK, but my version "test" that uses "test_profile" instead of SysML does not work.
In my investigation of how SysML profile is setup to achieve this (given I cannot find any good documentation of Papyrus profile creation that utilizes derived properties) I have investigated SysML.
Snippet from SysML/20181001/SysML.xmi 1.6 (Normative Machine Readable Documents from OMG SysML), after I have done the following for ease of readability:
- removed ownedComment,
- edited "->" to simply show "->",
- replaced "SysML.AbstractRequirement" and "SysML.DeriveReqt" with ".." as they appear in xmi:id fields;
As a result we have the following readable raw specification that probes the magic that makes derived and derivedFrom tick.
Specification of DeriveReqt Stereotype:
<packagedElement xmi:id="SysML.DeriveReqt" xmi:type="uml:Stereotype" name="DeriveReqt">
<generalization xmi:id=".._generalization.SysML.Trace" xmi:type="uml:Generalization" isSubstitutable="false">
<general xmi:idref="SysML.Trace"/>
</generalization>
<ownedRule xmi:id=".._rule.1_supplier_is_requirement" xmi:type="uml:Constraint" name="1_supplier_is_requirement">
<specification xmi:id=".._rule.1_supplier_is_requirement.specification" xmi:type="uml:OpaqueExpression" body="AbstractRequirement.allInstances().base_NamedElement->includesAll(self.base_Abstraction.client)" language="OCL" name="specification">
<type href="www.omg.org/spec/UML/20161101/PrimitiveTypes.xmi#Boolean"/>
</specification>
</ownedRule>
<ownedRule xmi:id=".._rule.2_client_is_requirement" xmi:type="uml:Constraint" name="2_client_is_requirement">
<specification xmi:id=".._rule.2_client_is_requirement.specification" xmi:type="uml:OpaqueExpression" body="AbstractRequirement.allInstances().base_NamedElement->includesAll(self.base_Abstraction.supplier)" language="OCL" name="specification">
<type href="www.omg.org/spec/UML/20161101/PrimitiveTypes.xmi#Boolean"/>
</specification>
</ownedRule>
</packagedElement>
Note: DeriveReqt has generalization relation to SysML.Trace which has Stereotype Extension of Abstraction metamodel type; i.e. has the property "base_Abstraction". So when recreating these structures as closely as possible to the SysML equivalent, this must also be taken into consideration, further below. Similarly SysML.AbstractRequirement has Stereotype Extension of NamedElement metamodel type.
Specification of AbstractRequirement Stereotype:
<packagedElement xmi:id="SysML.AbstractRequirement" xmi:type="uml:Stereotype" isAbstract="true" name="AbstractRequirement">
<ownedAttribute xmi:id="..base_NamedElement" xmi:type="uml:Property" name="base_NamedElement">
<lowerValue xmi:id="..base_NamedElement.lowerValue0" xmi:type="uml:LiteralInteger" name="" value="1"/>
<type href="www.omg.org/spec/UML/20161101/UML.xmi#NamedElement"/>
<upperValue xmi:id="..base_NamedElement.upperValue0" xmi:type="uml:LiteralUnlimitedNatural" name="" value="1"/>
</ownedAttribute>
<ownedAttribute xmi:id="..derived" xmi:type="uml:Property" isDerived="true" name="derived">
<lowerValue xmi:id="..derived.lowerValue0" xmi:type="uml:LiteralInteger" name=""/>
<type xmi:idref="SysML.AbstractRequirement"/>
<upperValue xmi:id="..derived.upperValue0" xmi:type="uml:LiteralUnlimitedNatural" name="" value="*"/>
</ownedAttribute>
<ownedAttribute xmi:id="..derivedFrom" xmi:type="uml:Property" isDerived="true" name="derivedFrom">
<lowerValue xmi:id="..derivedFrom.lowerValue0" xmi:type="uml:LiteralInteger" name=""/>
<type xmi:idref="SysML.AbstractRequirement"/>
<upperValue xmi:id="..derivedFrom.upperValue0" xmi:type="uml:LiteralUnlimitedNatural" name="" value="*"/>
</ownedAttribute>
<ownedOperation xmi:id="..getDerived_" xmi:type="uml:Operation" isQuery="true" name="getDerived">
<bodyCondition xmi:id="..getDerived_._rule.getDerived_body" xmi:type="uml:Constraint" name="getDerived_body">
<specification xmi:id="..getDerived_._rule.getDerived_body.getDerived_body_specification" xmi:type="uml:OpaqueExpression" body="DeriveReqt.allInstances()->select(base_Abstraction.supplier=self).base_Abstraction.client" language="OCL" name="getDerived_body_specification">
<type xmi:idref="SysML.AbstractRequirement"/>
</specification>
</bodyCondition>
<ownedParameter xmi:id="..getDerived_.return" xmi:type="uml:Parameter" direction="return" effect="read" name="return">
<lowerValue xmi:id="..getDerived_.return.lowerValue0" xmi:type="uml:LiteralInteger" name=""/>
<type xmi:idref="SysML.AbstractRequirement"/>
<upperValue xmi:id="..getDerived_.return.upperValue0" xmi:type="uml:LiteralUnlimitedNatural" name="" value="*"/>
</ownedParameter>
<ownedRule xmi:idref="..getDerived_._rule.getDerived_body"/>
</ownedOperation>
<ownedOperation xmi:id="..getDerivedFrom_" xmi:type="uml:Operation" isQuery="true" name="getDerivedFrom">
<bodyCondition xmi:id="..getDerivedFrom_._rule.getDerivedFrom_body" xmi:type="uml:Constraint" name="getDerivedFrom_body">
<specification
xmi:id="..getDerivedFrom_._rule.getDerivedFrom_body.getDerivedFrom_body_specification" xmi:type="uml:OpaqueExpression" body="DeriveReqt.allInstances()->select(base_Abstraction.client=self).base_Abstraction.supplier" language="OCL" name="getDerivedFrom_body_specification">
<type xmi:idref="SysML.AbstractRequirement"/>
</specification>
</bodyCondition>
<ownedParameter xmi:id="..getDerivedFrom_.return" xmi:type="uml:Parameter" direction="return" effect="read" name="return">
<lowerValue xmi:id="..getDerivedFrom_.return.lowerValue0" xmi:type="uml:LiteralInteger" name=""/>
<type xmi:idref="SysML.AbstractRequirement"/>
<upperValue xmi:id="..getDerivedFrom_.return.upperValue0" xmi:type="uml:LiteralUnlimitedNatural" name="" value="*"/>
</ownedParameter>
<ownedRule xmi:idref="..getDerivedFrom_._rule.getDerivedFrom_body"/>
</ownedOperation>
</packagedElement>
I had initially named the "test_profile" operations as getDerived and getDerivedBy just like SysML, however Papyrus complains about this because the "isDerived=true" properties "derived" and "derivedBy" don't have any way of deducing their values from same named operations as per UML standard (in section 6.4.1 of formal-17-12-05.pdf OMG UML specification):
Derivation: where an Attribute or Association End is marked as derived and is not a derived union, the derivation is specified by an Operation with the same name and type as the derived Attribute or Association End.
It is also strange that SysML names the operation that derives the values of "dervied" and "derviedBy" as "getDerived" and "getDerivedBy" - but it seems to work in the Papyrus registered profile "SysML". Which leads me to suspect there might be other Java code working in the background and that it might not just be the Papyrus profile...
Anyway, I have created projects "test" and "test_profile" to attempt to replicate this behaviour, however in my version of the "test" project, the derived Stereotype properties \derived and \derivedBy do not show A and B as they do with the "test_sysml" test program I made using SysML profile.
Please take a look and see if I'm doing something obviously wrong?
|
|
|
Re: Papyrus profiles with derived stereotype properties defined by same name operations [message #1835798 is a reply to message #1835775] |
Sun, 13 December 2020 10:59   |
Eclipse User |
|
|
|
Hi,
Your surmise was correct that the Papyrus SysML 1.6 implementation has custom Java code to make the derived properties of the Requirement stereotype work. And that implementation is not based on the UML convention of same-named operations; it is just a customization of the Java code generated for the profile by subclassing and overriding the property getter methods.
A better approach in generated code is actually like the UML convention, but relying on the Eclipse UML2 metamodel's extensions of EMF code generation. As you can see in the UML.merged.uml model in the org.eclipse.uml2.uml bundle, which is the source model for the generation of the Eclipse UML API, there are a great many operations that
- have protected visibility (in UML terms)
- have the same name as the derived property that they compute
- have the «eOperation» stereotype applied
- use the stereotype property to make the method name generated in the corresponding Ecore model be 'getXyz' instead of just 'xyz'
- specify suppressed visibility (an Ecore code generation concept) in that same stereotype
The UML metamodel also provides for generation of operations that require implementation "by hand" in custom code into separate XyzOperations classes to which the generated model classes delegate. This is more flexible than the subclassing technique employed by Papyrus SysML 1.6 and accounts for multiple inheritance as it relies on delegation, not subclassing. Moreover, by specifying Java "getXyz" method names, which actually go into the Ecore model required by the EMF run-time, that makes the base EMF code generation recognize that the operation implements the derivation of the property. All very tidy. But, it requires generating your Profile to Java code using the UML2 code generator.
In the example projects that you attached, the profile is a "dynamic profile" leveraging the dynamic capabilities of EMF. These do actually support the delegation of operation behaviour and feature derivation to "invocation delegates." There is a syntax of EAnnotations that you need to attach to the Ecore EPackage and the features/operations to make this work; that is documented in the Eclipse Wiki. To get those annotations in the dynamic Ecore model generated for your profile by the "profile definition" process, you need to ensure that the "Operation Bodies," "Derived Features," and "Invocation Delegates" options are set to "Process" in the profile definition dialog. It looks like you've done that in your profile definition as I see the relevant annotations on the package. But I don't think that EMF's derived feature delegation recognizes the UML convention of same-named operations. It requires the EStructuralFeature to have an annotation providing the delegation expression. I am not sure how you would specify that in the UML, because properties cannot own constraints at all (much less "body constraints" as operations do) and can only be constrained by owned rules of their owning class, but those must be boolean-valued because only the operation body constraint can actually compute a value. Perhaps you can use the «eReference» stereotype on your derived properties to explicitly model the annotations the EMF needs. I've never tried that.
Ultimately, I think your best bet would be to generate your profile to code in the way that the Papyrus SysML 1.6 profile is generated, but using Eclipse UML2's enhanced code generation capabilities, especially the "operations class" pattern for operations that are difficult to express with OCL. Note that code generation also supports delegation of operations to dynamic evaluation of OCL body constraints using the applicable generator options. So, you should be able to make the same-named-operation pattern that the UML2 metamodel itself uses to factor out custom code into "operations classes" to actually generate their "implementations" by delegation to OCL, so that you won't even have custom code to write. I don't know that I've tried this, myself, but it feels like it should work. Assuming that the code generation templates handling the same-named-operation pattern also understand the invocation delegate pattern.
HTH,
Christian
|
|
| | | | | | |
Re: Papyrus profiles with derived stereotype properties defined by same name operations [message #1836147 is a reply to message #1836136] |
Tue, 22 December 2020 09:06   |
Eclipse User |
|
|
|
Hi, Deniz,
Right, sorry, the mapping from the Ecore Profile (UML) to "suppressed visibility" in the GenModel isn't as direct as my phrasing seemed to make it. Your attachment "image1.png" has it right: it is the "none" visibility kind in the Ecore stereotypes for properties and operations. This attribute of the stereotype is picked up by the UML importer when it creates the GenModel element for the operation, to set the property that you show in "image2.png". There is no representation of this visibility concept in Ecore, unless perhaps it be via a codegen-specific annotation.
So, I think you have the complete picture here.
Best,
Christian
[Updated on: Tue, 22 December 2020 09:07] by Moderator
|
|
|
Re: Papyrus profiles with derived stereotype properties defined by same name operations [message #1836168 is a reply to message #1836147] |
Tue, 22 December 2020 22:36   |
Eclipse User |
|
|
|
Hi Christian,
Thank you for all this help, this is getting close...
When I define the plugin.xml file as per the default generated version as shown below, there are issues:
<plugin>
<extension point="org.eclipse.emf.ecore.generated_package">
<!-- @generated Requirements -->
<package
uri="http://www.eclipse.org/model/requirements"
class="requirements.RequirementsPackage"
genModel="model/Requirements.genmodel"/>
</extension>
</plugin>
Papyrus registered profile application doesn't list the custom created "Requirements" profile as shown in image4.png.
When I define additional entension point for org.eclipse.papyrus.uml.extensionpoints.UMLProfile as shown below, I can access the registered profile application in Papyrus, however I cannot apply the "Requirement" Stereotype to any Class:
<plugin>
<extension point="org.eclipse.emf.ecore.uri_mapping">
<mapping
source="pathmap://resources/model/"
target="platform:/plugin/Requirements_1.0.0/model/">
</mapping>
</extension>
<extension point="org.eclipse.papyrus.uml.extensionpoints.UMLProfile">
<profile
description="Basic example requirements profile"
name="Requirements 1.0"
path="pathmap://resources/model/Requirements.profile.uml"
provider="Deniz Eren">
</profile>
</extension>
<extension point="org.eclipse.emf.ecore.generated_package">
<!-- @generated Requirements -->
<package
uri="http://www.eclipse.org/model/requirements"
class="requirements.RequirementsPackage"
genModel="model/Requirements.genmodel"/>
</extension>
</plugin>
Papyrus registered profile application does list the custom created "Requirements" profile, but it cannot be applied to any of the classes A or B as shown in image5.png, image6.png and image7.png. After applying the Stereotype the "Applied Stereotypes" section of the class Profile is empty and later I get error messages reporting detached Stereotypes.
The only version I can get working is when I remove the generated extension org.eclipse.emf.ecore.generated_package, but that's just the same as applying Requirements.profile.uml as a non-registered profile and I suspect it isn't even using the Java generated code, as all the Constraints supplier_is_requirement and client_is_requirement behave as they would when you just apply non-registered profile Requirements.profile.uml:
<plugin>
<extension point="org.eclipse.emf.ecore.uri_mapping">
<mapping
source="pathmap://resources/model/"
target="platform:/plugin/Requirements_1.0.0/model/">
</mapping>
</extension>
<extension point="org.eclipse.papyrus.uml.extensionpoints.UMLProfile">
<profile
description="Basic example requirements profile"
name="Requirements 1.0"
path="pathmap://resources/model/Requirements.profile.uml"
provider="Deniz Eren">
</profile>
</extension>
</plugin>
Any pointers where the issue might be and how the plugin.xml should be configured?
I have also attached the experimental "Requirements" project as-is.
Attachment: image4.png
(Size: 159.23KB, Downloaded 116 times)
Attachment: image5.png
(Size: 158.86KB, Downloaded 125 times)
Attachment: image6.png
(Size: 127.43KB, Downloaded 94 times)
Attachment: image7.png
(Size: 130.82KB, Downloaded 106 times)
Attachment: Requirements.tar.gz
(Size: 97.91KB, Downloaded 92 times)
[Updated on: Wed, 23 December 2020 06:39] by Moderator
|
|
| |
Re: Papyrus profiles with derived stereotype properties defined by same name operations [message #1836235 is a reply to message #1836200] |
Fri, 25 December 2020 08:57   |
Eclipse User |
|
|
|
Hi, Deniz,
I suspect that one problem with the run-time behaviour of your profile is that it includes several dynamic definitions in addition to being generated. A profile should be either statically defined (generated), or dynamically defined, not both. I think the UML API is finding the dynamic definition in some cases, and so not looking for the static definition, leading to unexpected results because the dynamic definition is less capable.
You should delete the UML annotation in the profile that contains all of its dynamic EPackage definitions and always ignore the prompt to define the profile when saving it. And, really, Papyrus ought to detect that the profile has an accompanying GenModel and never prompt to define it dynamically. That would be worth raising in Bugzilla.
HTH,
Christian
|
|
|
Re: Papyrus profiles with derived stereotype properties defined by same name operations [message #1836361 is a reply to message #1836235] |
Wed, 30 December 2020 02:52   |
Eclipse User |
|
|
|
Hi Christian,
Happy to raise any bug reports once the issue is resolved, but I now tried with and without the dynamic profile definition with no luck.
So I went back to the drawing board to eliminate any unknowns, I re-installed eclipse (the new eclipse/modeling-2020-12). I stopped trying to get the fancy derived property working and just have a simple Stereotype extending an Abstraction, with no other contents. I followed the text book description of static profiles from documentation:
https://help.eclipse.org/2020-12/topic/org.eclipse.papyrus.uml.diagram.profile.doc/target/generated-eclipse-help/users/generatingStaticProfiles.html?cp=74_0_1_8_5
But when I try to create a Papyrus UML model to apply this registered profile, it allows me to find and apply it to the package, but when I try to apply it to an Abstraction element it doesn't display the Stereotype. I looked in the Test.uml file and see:
<?xml version="1.0" encoding="UTF-8"?>
<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:testplugin="http://www.mycompany.com/Testplugin/1" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML">
<uml:Model xmi:id="_slOegEpsEeu6tYPtsHWdHw" name="Test">
<packageImport xmi:type="uml:PackageImport" xmi:id="_srHEEEpsEeu6tYPtsHWdHw">
<importedPackage xmi:type="uml:Model" href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#_0"/>
</packageImport>
<packagedElement xmi:type="uml:Class" xmi:id="_BozpMEpxEeuASrB-BFX7sQ" name="A"/>
<packagedElement xmi:type="uml:Class" xmi:id="_CSxzQEpxEeuASrB-BFX7sQ" name="B"/>
<packagedElement xmi:type="uml:Abstraction" xmi:id="_C_GtwEpxEeuASrB-BFX7sQ" client="_BozpMEpxEeuASrB-BFX7sQ" supplier="_CSxzQEpxEeuASrB-BFX7sQ"/>
<profileApplication xmi:type="uml:ProfileApplication" xmi:id="_A4bVIEpxEeuASrB-BFX7sQ">
<eAnnotations xmi:type="ecore:EAnnotation" xmi:id="_A4fmkEpxEeuASrB-BFX7sQ" source="http://www.eclipse.org/uml2/2.0.0/UML">
<references xmi:type="ecore:EPackage" href="http://www.mycompany.com/Testplugin/1#/"/>
</eAnnotations>
<appliedProfile xmi:type="uml:Profile" href="pathmap://MYLANG_PROFILE/testplugin.profile.uml#_wMd84EpqEeuF1anrashfZA"/>
</profileApplication>
</uml:Model>
<testplugin:Stereotype4 xmi:id="_DwEQoEpxEeuASrB-BFX7sQ"/>
<testplugin:Stereotype4 xmi:id="_aopK4EpxEeuASrB-BFX7sQ"/>
</xmi:XMI>
The Stereotype application segment references unknown xmi:id's also as expected, being reported as dangling stereotypes by Papyrus:
<testplugin:Stereotype4 xmi:id="_DwEQoEpxEeuASrB-BFX7sQ"/>
<testplugin:Stereotype4 xmi:id="_aopK4EpxEeuASrB-BFX7sQ"/>
So as you can see I'm just trying to get a simple static profile working now and no luck. I've attached the profile and model I tried to replicate from the documentation link above.
I also tried to experiment with the location I'm installing the plugin, i.e. /home/deniz/eclipse/modeling-2020-12/eclipse
The way I'm installing the plugin to my workspace is by clicking on File -> Export -> Select Plug-in Development [Deployable plug-ins and fragments] -> Install into host. Repository: /home/deniz/eclipse/modeling-2020-12/eclipse
Is there something obviously wrong with what I'm doing? Because I'm just after getting a "hello world" Papyrus static profile plug-in working now ONLY ....
Your help is appreciated!
Best regards,
Deniz
|
|
| | | | | | | | | | |
Re: Papyrus profiles with derived stereotype properties defined by same name operations [message #1836392 is a reply to message #1836391] |
Fri, 01 January 2021 05:21   |
Eclipse User |
|
|
|
Ed, Christian,
One problem I've found, regarding fact that setBaseClass isn't called by the framework, is that the default generated code has this:
// Initialize classes, features, and operations; add parameters
initEClass(testStereotypeEClass, TestStereotype.class, "TestStereotype", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
initEReference(getTestStereotype_BaseClass(), theUMLPackage.getClass_(), null, "baseClass", null, 0, 1, TestStereotype.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, !IS_ORDERED);
But notice "baseClass" should be "base_Class" - when I make this change the setBaseClass routine does get called by the framework, and the uml file looks better:
<mylanguage:TestStereotype xmi:id="_8-evgEwaEeu4fux5zoKFGQ" base_Class="_mx6RYEvzEeuPDv5Fd9D50A"/>
Before it was:
<mylanguage:TestStereotype xmi:id="_hb5kQEwaEeuwKZLS0lr_fA"/>
However it's still not showing the applied stereotype after application - there must be more things wrong with the generated code?
[Updated on: Fri, 01 January 2021 05:25] by Moderator
|
|
| | | | | | | | | | |
Re: Papyrus profiles with derived stereotype properties defined by same name operations [message #1836844 is a reply to message #1836422] |
Fri, 15 January 2021 08:50   |
Eclipse User |
|
|
|
Hi Ed, hi Christian,
The issue of getting a basic Papyrus static profile working is now SOLVED!
Next step is for me to return to the original issue of getting the derived property magic working as discussed early on with Christian (will post future comment to summarise that when I get it working). However, in this comment I'm summarising the findings of getting the basic static profile working and how to get past the "base_Class" to "baseClass" naming issue and resultant static profile failure as discussed above.
Firstly on an unrelated note, because I want to also use the SysML 1.6 profile (for purposes other than the items discussed in this thread), I installed Eclipse Modelling Version 2020-06. Looking at the SysML 1.6 Git repository the last officially tested version seems to be 2020-06 as of this date. Also I tried 2020-12 and it gives some strange string error, so for the time being I'm using 2020-06.
Then using the Eclipse Marketplace I installed SysML 1.6 and via the dependencies it installed Papyrus for UML 4.8.0. Just mentioning versions for future reference just in case it is important to future readers, however the features discussed are common for a long time. I am also not sure if the issues discussed are bugs or expected behaviour. Anyway, I am writing this comment for future readers that have come across the same issues.
Firstly I followed the Generating Static Profiles section of the Papyrus Guide:
https://help.eclipse.org/2020-12/topic/org.eclipse.papyrus.uml.diagram.profile.doc/target/generated-eclipse-help/users/generatingStaticProfiles.html?cp=73_0_1_8_5
UML Import Options seemed unimportant/irrelevant to me and at least the Papyrus Guide didn't have any further documentation on what exactly these Options do. In short - do NOT overlook or underestimate these options! Here are my findings...
In the UML Import section after clicking on your profile.uml model or clicking "Load" with the default Options as shown also in the Papyrus Guide, there will be a number of warnings given such as: "Feature 'UML::Element::ownedElement' should be annotated as a union and made non-changeable".
Originally I was clicking on "Process All" to make these warnings go away, however I stopped doing that and instead ignored the warnings and clicked Next.
Then followed the rest of the Papyrus Guide and set the Extensions etc...
To test (most would know this but thanks to Christian this was a good learning for me) - from the menu click on "Run" -> "Run Configurations" then under the tab "Eclipse Application" create a new configuration. If you check the "Plug-ins" tab you will see the default settings "all workspace and enabled target plug-ins" will mean your test profile "com.mylanguage.profile" will be installed to the test workspace instance that will start when you Run the configuration.
Inside the Run configuration Eclipse environment create a simple Papyrus UML model and apply your registered profiled and it will all work as expected!
Now to analyse which UML Import Option broke the generated code, I did the following tests...
Firstly I created a simple Git repository and committed the working copy. This is useful to track what will change when we generate static profile code with different UML Import Options.
Next I attempted UML Import once again and changed Options to firstly get rid of all the UML metamodel warnings to satisfy my OCD and to get all the minimum features/options needed to get a warning free generation. To achieve this I had to activate (set to Process) the following options:
- Union Properties,
- redefining Operations,
- redefining Properties,
- Subsetting Properties,
- Duplicate Operations,
- Duplicate Features.
This makes sense since UML metamodel uses all these UML concepts - amazing how UML defines UML :)
After these changes the model continues to work fine and there are no warnings during UML Import.
Next aim at this stage was to identify which UML Import Option is actually causing the "base_Class" to become "baseClass" and thus breaking the generated static profile code. So one by one I turned on the remaining Options to "Process" mode and generated the code until the "base_Class" became "baseClass":
- Duplicate Feature Inheritance -> still OK,
- Duplicate Operation Inheritance -> still OK,
- Validate Delegates -> still OK,
- Non-API Invariants -> still OK,
- Operation Bodies -> still OK,
- Invocation Delegates -> still OK,
- Property Default Expressions -> still OK,
- Camel Case Names -> BROKEN! "base_Class" became "baseClass" !!!
The UML Import option "Camel Case Names" seems to be the cause of the failure! Make sure this is set to "Ignore". In hindsight the name of this option is quite a clue, but like said, if only there was some documentation explaining these options and what they do! :)
Further, I noticed "Opposite Role Names" is also something that causes some difference in code - in particular function createEmofAnnotations appears in the Java generated code, which seems to annotate some base_Class related functionality. Anyway, when this option is set to "Process" the resultant static profile still works fine.
Next I will go back and try to get derived property feature working, like I was trying in the very beginning.
|
|
| | |
Re: Papyrus profiles with derived stereotype properties defined by same name operations [message #1836961 is a reply to message #1836865] |
Wed, 20 January 2021 05:29   |
Eclipse User |
|
|
|
Hi,
For future readers that are also interested in static profiles, attached is my now working solution. It contains the static profile within a small Git repo and a "Test" UML model that utilises it.
I have not been able to get the EOperation auto-generated derived property method to work, however I prefer to use the same way SysML solves this problem, by manually coding the desired behaviour in Java.
In the example here, check the class RequirementImpl for the hand coded Java for getDerived and getDerivedFrom functions. For example:
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
@Override
public EList<NamedElement> getDerived() {
// This should return the Requirement(s) derived from current
EList<NamedElement> derived = new BasicEList<>();
if (getBase_NamedElement() != null) {
Iterator<DirectedRelationship> itDep = getBase_NamedElement().getTargetDirectedRelationships().iterator();
// Find DeriveReqt link
while (itDep.hasNext()) {
DirectedRelationship currentDirectedRelationship = itDep.next();
DeriveReqt currentDeriveReqt = UMLUtil.getStereotypeApplication(currentDirectedRelationship, DeriveReqt.class);
if (currentDeriveReqt != null) {
EList<NamedElement> clients = currentDeriveReqt.getBase_Abstraction().getClients();
Iterator<NamedElement> it = clients.iterator();
while (it.hasNext()) {
derived.add(it.next());
}
}
}
}
return new UnmodifiableEList<>(this, MyRequirementsPackage.eINSTANCE.getRequirement_Derived(), derived.size(), derived.toArray());
}
This code blocked replaced the auto-generated code:
// TODO: implement this method to return the 'Derived' reference list
// Ensure that you remove @generated or mark it @generated NOT
throw new UnsupportedOperationException();
P.S. you must also set "@generated" in the function comment block to "@generated NOT" to prevent auto-generation overriding the handwritten code.
|
|
| | |
Re: Papyrus profiles with derived stereotype properties defined by same name operations [message #1837098 is a reply to message #1836983] |
Fri, 22 January 2021 01:13   |
Eclipse User |
|
|
|
Hi,
Found another problem.
When your model contains OCL that refers to a UML type for example something like self.base_Element.oclIsKindOf(UML::Comment) the generated static profile Java code gives an exception when it runs, saying:
org.eclipse.ocl.ecore.delegate.OCLDelegateException: Unknown type ([UML, Comment])
On closer examination, when for example an OCL expression as mentioned exists Papyrus is happy with this expression. However the static profile generated Java code looks like this:
addAnnotation
(getDocumentSection__WordWrapAt(),
source,
new String[] {
"body", "self.base_Element.oclIsKindOf(UML::Comment)"
});
This when run give the exception as previously mensioned.
However, after generating the Java code if I manually modify the code by changing the "UML::" to lowercase "uml::" (as I suspected from other expressions I've seen in ecore Java usage), then everything works fine. Like said I have to manually edit generated code to look like this for it to work:
addAnnotation
(getDocumentSection__WordWrapAt(),
source,
new String[] {
"body", "self.base_Element.oclIsKindOf(uml::Comment)"
});
On the same token however, when dealing with UML PrimitiveTypes such as UML::Boolean, UML::String, UML::UnlimitedNatural, UML::Integer and UML::Real - they work fine with "UML" or "uml" from EMF Java perspective without exceptions being thrown. However Papyrus profile model only accepts the upper case "UML" as valid OCL.
This is less than ideal - is there something I've missed or should I create yet another bugzilla item? If yes, then which product would this bug fall under, Papyrus Core or EMF or is there a separate category for UML? Those bugzilla categories are quite confusing.
Best regards,
Deniz
[Updated on: Fri, 22 January 2021 01:19] by Moderator
|
|
| | | | | | | |
Re: Papyrus profiles with derived stereotype properties defined by same name operations [message #1837279 is a reply to message #1837277] |
Tue, 26 January 2021 22:27   |
Eclipse User |
|
|
|
I first changed the OCL expression to something more interesting such as "self.base_Element.oclIsKindOf(UML::Comment)", then I applied the stereotype to a Class, Enumeration and Comment.
I got it working if I edit the generated code in two functions and change the "String source = "http://www.eclipse.org/emf/2002/Ecore/OCL"" line to "String source = "http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot"":
/**
* Initializes the annotations for <b>http://www.eclipse.org/emf/2002/Ecore</b>.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected void createEcoreAnnotations() {
String source = "http://www.eclipse.org/emf/2002/Ecore";
addAnnotation
(this,
source,
new String[] {
//"validationDelegates", "http://www.eclipse.org/emf/2002/Ecore/OCL"
"validationDelegates", "http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot"
});
addAnnotation
(stereotype1EClass,
source,
new String[] {
"constraints", "Constraint1"
});
}
/**
* Initializes the annotations for <b>http://www.eclipse.org/emf/2002/Ecore/OCL</b>.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected void createOCLAnnotations() {
//String source = "http://www.eclipse.org/emf/2002/Ecore/OCL";
String source = "http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot";
addAnnotation
(stereotype1EClass,
source,
new String[] {
"Constraint1", "self.base_Element.oclIsKindOf(UML::Comment)"
});
}
Now the question; is there a way to tell genmodel to use www.eclipse.org/emf/2002/Ecore/OCL/Pivot in the generated code string "source" rather than www.eclipse.org/emf/2002/Ecore/OCL?
[Updated on: Tue, 26 January 2021 22:29] by Moderator
|
|
| | | | | | | |
Goto Forum:
Current Time: Sun Jul 27 18:57:09 EDT 2025
Powered by FUDForum. Page generated in 0.45176 seconds
|