Sparx Systems Forum
Enterprise Architect => General Board => Topic started by: Eran Peleg on February 04, 2021, 02:21:55 am
-
Hi
I have a profile model with Stereotype (ST) A, B, C. A is an abstract ST, while both B and C are inherited from A. I would like to run the same Shape-Script in B and C. So, I tried to put the script in A and let it run in B and C. It doesn't ... what should I specify in B and C in order to run A's script on Elements with B or C ST?
Thanks
Eran
-
IIRC inheritance does not work for shape script. You would need to copy the shape scripts across the inheriting stereotypes.
q.
-
IIRC inheritance does not work for shape script. You would need to copy the shape scripts across the inheriting stereotypes.
q.
q is correct, not only does inheritance not work, but you can't even call common routines. We have to duplicate the same script fragments across each stereotype!
a REAL PITA!
Paolo
-
Hello all,
I tried the following on the latest build, and it seems to work fine:
- add two <<stereotype>> elements A and B, and add a <<metatype>> of Class
- connect A and the Class metatype by Extension
- define a ShapeScript to A
- connect A and B by Generalization (A is parent)
When I drag&drop A or B from the Toolbox, both are drawn as the defined ShapeScript.
HTH,
-
Hmm. Interesting. I made a test with 13.5 where the inheritance now worked. Pretty sure it didn't with the same version a short time before since we assumed it to work but did not why we copied scripts. I would guess this is some kind of random behavior which would not surprise me. Anyhow, I have to have a close look.
q.
-
This IS a new (to me) development as I remember several years ago trying the same thing (and failing)
-
Hello all,
I tried the following on the latest build, and it seems to work fine:
- add two <<stereotype>> elements A and B, and add a <<metatype>> of Class
- connect A and the Class metatype by Extension
- define a ShapeScript to A
- connect A and B by Generalization (A is parent)
When I drag&drop A or B from the Toolbox, both are drawn as the defined ShapeScript.
HTH,
Hi Takeshisan,
Do you mean they were drawn with the same shapes? I haven't tried it as I'm in transit. I think what we are after is being able to extend the shapescript (i.e. add additional renderings) in the descendent.
There may be some utility in the ability to reuse the same shapescript in the descendants, but it's not true inheritance. As you know, inheritance formally requires either a change in attributes or methods - otherwise, it is just a restriction.
Paolo
-
There's definitely something fishy. I created test stereo like above and switching the stereo manually showed inheritance fro the script. BUT when trying to add this "stand alone" stereo (as I did not any extends relation) it does not show up in the toolbox (you just see the «» symbol). You can probably say: works as designed - by Sparx.
q.
-
Do you mean they were drawn with the same shapes? I haven't tried it as I'm in transit. I think what we are after is being able to extend the shapescript (i.e. add additional renderings) in the descendent.
Hi Paolo,
I am sorry I misunderstood the theme. My understanding is defining Stereotype (ST) A, B, C (A is an abstract ST, while both B and C are inherited from A) and running the same Shape-Script in B and C. I did not think to extend the shapescript (i.e. add additional renderings).
Sorry, please ignore my comment.
-
There may be some utility in the ability to reuse the same shapescript in the descendants, but it's not true inheritance. As you know, inheritance formally requires either a change in attributes or methods - otherwise, it is just a restriction.
Why do you say that inheritance requires a change? You could argue that it's not meaningful if you don't add/change something, but that's not part of the definition.
In any case.. with the following shape scripts you can re-use the base and add an additional rendering.
Ashape main{
rectangle(0,0,100,100);
println("#name#");
}
Bshape main{
drawparentshape();
ellipse(10,10,30,30);
}
Cdecoration x
{
moveto(0,0);
lineto(100,100);
moveto(100,0);
lineto(0,100);
}
There are limitations. There is no allowance for overriding a decoration used in the base with a new one in the specialized stereotype.
In UML terms, the main script is redefinable. All decorations are added to the collection.
-
There may be some utility in the ability to reuse the same shapescript in the descendants, but it's not true inheritance. As you know, inheritance formally requires either a change in attributes or methods - otherwise, it is just a restriction.
Why do you say that inheritance requires a change? You could argue that it's not meaningful if you don't add/change something, but that's not part of the definition.
In any case.. with the following shape scripts, you can re-use the base and add an additional rendering.
Ashape main{
rectangle(0,0,100,100);
println("#name#");
}
Bshape main{
drawparentshape();
ellipse(10,10,30,30);
}
Cdecoration x
{
moveto(0,0);
lineto(100,100);
moveto(100,0);
lineto(0,100);
}
There are limitations. There is no allowance for overriding a decoration used in the base with a new one in the specialized stereotype.
In UML terms, the main script is redefinable. All decorations are added to the collection.
(my emphasis)
Thanks, Eve for the information, definitely food for thought here!
As to inheritance requiring a change, I think Bertrand Meyer in OOSC2 makes that point. But in any case, if inheritance means "X is a type of Y" but X is no different from Y then "X IS a Y" not "a type of" Y. Difference (as a requirement) is implied.
I'll have a play with your example (when time and resources permit) and see how the uses you describe would be useful.
Paolo
-
[SNIP]
There are limitations. There is no allowance for overriding a decoration used in the base with a new one in the specialized stereotype.
In UML terms, the main script is redefinable. All decorations are added to the collection.
Hi Eve,
I haven't had time yet to take a closer look at this. But, do I understand correctly, that if we have a set of standard decorations that many of our shapescripts use and we put them into a supplemental stereotype, we can use multiple-inheritance to automatically include those decorations in the specialized stereotype? In your example, rather than A<-B<-C I have A<-B & C and create B<-D->C D will execute both sets of shapescripts?
Paolo
-
I have a stereo «TBD» which just colors an element red via shape script. That had always worked. No inheritance, though. It's plain assignment of multiple stereotypes.
q.
-
I have a stereo «TBD» which just colours an element red via shape script. That had always worked. No inheritance, though. It's the plain assignment of multiple stereotypes.
q.
We've found that we can make all this happen "behind the scenes" with inheritance and supplementals so that we still retain (in the main) the ability to end up with only a single stereotype (the metatype) for the item. That's why I'm hoping the answer to my question is "yes!".
Paolo
-
[SNIP]
There are limitations. There is no allowance for overriding a decoration used in the base with a new one in the specialized stereotype.
In UML terms, the main script is redefinable. All decorations are added to the collection.
Hi Eve,
I haven't had time yet to take a closer look at this. But, do I understand correctly, that if we have a set of standard decorations that many of our shapescripts use and we put them into a supplemental stereotype, we can use multiple-inheritance to automatically include those decorations in the specialized stereotype? In your example, rather than A<-B<-C I have A<-B & C and create B<-D->C D will execute both sets of shapescripts?
Paolo
Rather than try to recreate Eve's example in a test profile, I tried to create my example above in our main profile (I could do it pretty easily). So, as I mentioned we have a bunch of decorations which occur in a large number of our stereotypes. We currently maintain the shapescript with an external editor which updates the decoration set.
So I exported the set of decorations into a new stereotype StandardItemDecorations and placed them in its _image attribute. No other attributes were defined. I then removed them from the main stereotype Item(Generic) and had Item(Generic) inherit from StandardItemDecorations. As I understand what Eve is saying, this should have worked seamlessly. It didn't work at all. :( The decorations no longer responded to the properties that drive them. Switching back and forwards between the two versions of Item(Generic) proved this.
Now that I've been using the model-based definitions for a while, I checked the emitted XML and everything looked as I expected. Am I missing some secret sauce? For example, do I need a "shape main" in the supplementary stereotype?
Paolo
-
I tried Eve's suggestion here is the diagram.
(https://i.imgur.com/KWSt5tV.png)
Did I understand her correctly?
Because, if I did, the output for the profile is quite peculiar...
Any ideas?
[EDIT: caused by my accidentally forgetting to set the package stereotype to "profile" - ignore previous versions of this post.]
TIA,
Paolo
-
Are you able to expose C (or B) in a toolbox? I was not (which I said in a previous comment). Only if there's an explicit extends then the stereo will be shown in the toolbox.
q.
-
Are you able to expose C (or B) in a toolbox? I was not (which I said in a previous comment). Only if there's an explicit extends then the stereo will be shown in the toolbox.
q.
No, I couldn't either. So I'll try that.
Paolo
[EDIT: That did the trick!
(https://i.imgur.com/jBTj6PX.png)]
-
[SNIP]
Now that I've been using the model-based definitions for a while, I checked the emitted XML and everything looked as I expected. Am I missing some secret sauce? For example, do I need a "shape main" in the supplementary stereotype?
Paolo
As noted elsewhere, the "Secret Sauce" was to include the extension to the metaclass. Shapescripts don't seem to be activated if there is no such link. Can anyone confirm?
Some more experimentation required to find the "envelope" within which we have to work, but looking good, so far!
Paolo
-
[SNIP]
Some more experimentation required to find the "envelope" within which we have to work, but looking good, so far!
OK, so I've done some further experimenting and it's raised several questions. However, I think I'm able to achieve what we're after, but it seems clumsier than I would have thought.
I'll use the diagram below to illustrate and set up my questions. NOTE: This is NOT what we ended up with but allows me to discuss the issues we found.
(https://i.imgur.com/peETj7I.png)
Initially, we had only StndrdItm¯S, no metaclass. The inheritance failed completely (as previously discussed).
So, since the Item(Generic) was a Class, we added the Class metatype as a direct extension to StndrdItm¯S. This worked and Item(Generic) inherited the decorations correctly.
We wanted to extend this capability to an Activity-based stereotype BusinessProcess. We tried merely having BusinessProcess inherit from StndrdItm¯S, but, as expected, this failed (Activities can't inherit from Classes).
So, we added the Activity metaclass to StndrdItm¯S. Still no go (not unexpected. It looks as though being able to have multiple extensions has failed for the last few versions - can anyone confirm?)
Next we created the structure in the diagram. Each item type gets its own metaclass to inherit from. So now Item(Generic) inherits from StndrdClss¯S and BusinessProcess inherits from StndrdActvty¯S. With this structure, we can drag the items from the toolbox, but the decorations shapescript is NOT inherited (from StndrdItm¯S).
This was a shame, but we then copied the _image attribute from StndrdItm¯S to both StndrdClss¯S and StndrdActvty¯S and voila, it works!
My questions are:
Can this (notionally) redundant cloning of the shapescript avoidable?
Is multiple extension broken? If it was fixed, should everything be able to inherit from a multi-extended StndrdItm¯S?
TIA,
PAolo
-
Basically I would expect your first model (up this page) to work. As it does not, Sparx has implemented, well, selective, ignorant or just sparxian inheritance. In any case it's irrelevant whether I think it's a bug.
q.
-
My initial test had both B and C inheriting from A directly, while A held the only extends relationship.
Making C inherit from B instead resulted in it not getting the decoration from A. The reverse (inheritance C -> A, B -> C) resulted in B not drawing the main shape from A. That's not the behavior I expected, but it does align with what you have described.
I also saw that the shape script isn't picked up by the specializations in the situation like your last diagram. I can't explain why that would be either.
-
My initial test had both B and C inheriting from A directly, while A held the only extends relationship.
Making C inherit from B instead resulted in it not getting the decoration from A. The reverse (inheritance C -> A, B -> C) resulted in B not drawing the main shape from A. That's not the behaviour I expected, but it does align with what you have described.
I also saw that the shape script isn't picked up by the specializations in the situation like your last diagram. I can't explain why that would be either.
Thanks, Eve,
So should I report a defect? I have already reported inheritance defects with USDPs etc.
Also, do you have any comment on my multiple extension question? It used to work in the past for things like Association (arc) and AssociationClass (vertex), but now seems broken.
Finally, is qwerty's observation that without the extension, the stereotype won't work correctly in the toolbox correct?
[EDIT: Defect reported]
Paolo
-
I have received a reply from Sparx regarding the defect I mentioned.
Hello Paolo,
Thanks for the email.
My investigation shows that a stereotyped element will display decorations from its stereotype and from that stereotype's immediate generalization, but doesn't recurse up the stereotype hierarchy.
See the attached screenshot "Shape Test.png".
We will fix this in a future release.
Issue ID: 21027012
Were there any other unresolved issues from that forum thread?
This clarifies matters, but I've now discovered what appears to be a further defect.
We have made EXTENSIVE use of decorations to surface properties of the item. We can have (currently) up to 5 "widgets" in a particular orientation of the item (NW,N,NE,E,SE,S,SW,W & CENTER). However, when we separate the widgets via inheritance (Generalization), this breaks. NOTE: so long as the widgets don't overlap, it works fine for a given shapescript.
If we have a shape script (for stereotype G) that has:
shape main
{
}
decoration A
{
(NE)
}
decoration B
{
(NE)
}
If I now extract decoration A & B into a separate stereotype J
and reduce Shapescript G to just
shape main
{
}
and have a Generalization from G to J, it works as expected.
However, if I split each decoration into Stereotype A & Stereotype B - each one consisting only of the decoration - remove the generalization to J and add the generalizations to A & B, it now fails.
In other words, if it works in two of the above use cases, it should also work for the third!
In my view, this is a defect, but before I formally report it, I'd welcome feedback.
TIA,
PAolo
-
I suspect shape script to be some of those quick designs being implemented (from brain to keyboard) and never designed. Just a look at the poor language design makes that clear. (Just as a fun fact: comments were only introduced a couple of years ago after I sent a feature request.) So I would not be astonished to find more kind of weirdness as I already did.
q.
-
My initial test had both B and C inheriting from A directly, while A held the only extends relationship.
Making C inherit from B instead resulted in it not getting the decoration from A. The reverse (inheritance C -> A, B -> C) resulted in B not drawing the main shape from A. That's not the behaviour I expected, but it does align with what you have described.
I also saw that the shape script isn't picked up by the specializations in the situation like your last diagram. I can't explain why that would be either.
Thanks, Eve,
So should I report a defect? I have already reported inheritance defects with USDPs etc.
Also, do you have any comment on my multiple extension question? It used to work in the past for things like Association (arc) and AssociationClass (vertex), but now seems broken.
Finally, is qwerty's observation that without the extension, the stereotype won't work correctly in the toolbox correct?
[EDIT: Defect reported]
Paolo
Hi Sparxians, Any chance this could be answered definitively? I've just spent another few hours diagnosing this to be the issue in an inheritance hierarchy... Sometimes it seems to work and other times it's "screwed".
Paolo
[Edit:
The question I'm looking for an answer to is "Does multiple extension work"? That is if you have a single
<AppliesTo>
<Apply type="Class"/>
</AppliesTo>
Things will work (i.e. the item can be dragged from the toolbar)
If there are multiple,
<AppliesTo>
<Apply type="Activity"/>
<Apply type="Class"/>
</AppliesTo>
It will not drag...]
-
If you want a definitive answer, go through the support form.
The question I'm looking for an answer to is "Does multiple extension work"? That is if you have a single
<AppliesTo>
<Apply type="Class"/>
</AppliesTo>
Things will work (i.e. the item can be dragged from the toolbar)
If there are multiple,
<AppliesTo>
<Apply type="Activity"/>
<Apply type="Class"/>
</AppliesTo>
It will not drag...]
How is your toolbox defined? If you have "Profile::Stereotype" in the default field it needs to work out for itself which metaclass you want to drop. It can (usually?) do this if there's only one metaclass, but it can't if there are multiples.
That's why the preferred way to reference the item is with "Profile::Stereotype(UML::Metaclass). My personal experience is that it has always worked if I've specified the extension to use.
-
If you want a definitive answer, go through the support form.
The question I'm looking for an answer to is "Does multiple extension work"? That is if you have a single
<AppliesTo>
<Apply type="Class"/>
</AppliesTo>
Things will work (i.e. the item can be dragged from the toolbar)
If there are multiple,
<AppliesTo>
<Apply type="Activity"/>
<Apply type="Class"/>
</AppliesTo>
It will not drag...]
How is your toolbox defined? If you have "Profile::Stereotype" in the default field it needs to work out for itself which metaclass you want to drop. It can (usually?) do this if there's only one metaclass, but it can't if there are multiples.
That's why the preferred way to reference the item is with "Profile::Stereotype(UML::Metaclass). My personal experience is that it has always worked if I've specified the extension to use.
I didn't explain myself well enough. The stereotype involved is NOT the one on the toolbar. It's one of the antecedents. The one to drag is clear and singular. I would have expected that so long as the dropped metaclass was one of the multiples in the antecedent, it should be OK.
The only thing I changed (and manually for test purposes) was the line indicated - in the antecedent. If the dropped metaclass is NOT one of the multiples, it won't drop and that is understandable.
Paolo
-
Well, it seems that notwithstanding that if the concrete metatype is defined as a single metaclass, if there are multiple metaclasses in the inheritance tree, you have to specifically (and I would argue redundantly) specify the draggable metaclass in the concrete toolbox specification.
<Profile>::<Metatype> is defined as a Class (and ONLY a Class) - via extension. To have to say <Profile>::<Metatype>(UML::Class) is, surely redundant. It still strikes me as a code "smell". Still, at least I don't have to redesign our inheritance tree for the second time in a couple of days.
So, thanks for the hint, Eve. It's replaced a large pile of work with a smaller pile of work to specify the explicit metaclass on the toolbox items.
Paolo
-
I didn't explain myself well enough. The stereotype involved is NOT the one on the toolbar. It's one of the antecedents. The one to drag is clear and singular. I would have expected that so long as the dropped metaclass was one of the multiples in the antecedent, it should be OK.
Doesn't matter where you are going to drop the stereotype. If the stereotype on the toolbox can't determine a metaclass when you start a drag it won't work.
<Profile>::<Metatype> is defined as a Class (and ONLY a Class) - via extension. To have to say <Profile>::<Metatype>(UML::Class) is, surely redundant. It still strikes me as a code "smell".
Two points. It's <Profile>::<Stereotype>, not <Profile>::<Metatype>. As I said, if there is only one possible extension it does work it out. The only time (I know of) where it can't work it our for a single extension is if that extension is to an abstract metaclass. The problem is when you omit the extension by habit and are then surprised when it doesn't work when you have more than one. That's why it's recommended to include it explicitly.
-
I didn't explain myself well enough. The stereotype involved is NOT the one on the toolbar. It's one of the antecedents. The one to drag is clear and singular. I would have expected that so long as the dropped metaclass was one of the multiples in the antecedent, it should be OK.
Doesn't matter where you are going to drop the stereotype. If the stereotype on the toolbox can't determine a metaclass when you start a drag it won't work.
<Profile>::<Metatype> is defined as a Class (and ONLY a Class) - via extension. To have to say <Profile>::<Metatype>(UML::Class) is, surely redundant. It still strikes me as a code "smell".
Two points. It's <Profile>::<Stereotype>, not <Profile>::<Metatype>. As I said, if there is only one possible extension it does work it out. The only time (I know of) where it can't work it out for a single extension is if that extension is to an abstract metaclass. The problem is when you omit the extension by habit and are then surprised when it doesn't work when you have more than one. That's why it's recommended to include it explicitly.
OK, my bad on <Profile>::<Stereotype>, vs <Profile>::<Metatype>. (It's force of habit! I thought <Profile>::<Stereotype>, but wrote <Profile>::<Metatype>.)
I think your explanation should be expanded to be clearer... "if there is only one possible extension all the way up the inheritance hierarchy it does work it out.
Now to figure out how to respecify the toolboxes (and there are MANY) most efficiently!
Paolo
BTW: From the observed behaviour and your explanations, if you have a multiple extension in the hierarchy [1] it would seem pointless to have to define the toolbox item within the model as a specific metaclass extension since it needs to be overridden at the toolbox in any event. Is that observation correct?
Indeed, we ran a test <Profile>::<Sterotype> is directly defined as a Class (and ONLY a Class) - via extension and thus has the section:
<AppliesTo>
<Apply type="Class">
<Property name="_HideMetaclassIcon" value="true"/>
<Property name="isActive" value=""/>
</Apply>
</AppliesTo>
and yet, if we define the toolbox entry as <Profile>::<Sterotype>(UML::Activity), we will get an Activity. This also smells.
[1] Since we want to achieve commonality of decorations efficiently, it is likely that EVERY toolbox item will have a multi extension at least once in its inheritance hierarchy.
-
I think your explanation should be expanded to be clearer... "if there is only one possible extension all the way up the inheritance hierarchy it does work it out.
Accepted.
BTW: From the observed behaviour and your explanations, if you have a multiple extension in the hierarchy [1] it would seem pointless to have to define the toolbox item within the model as a specific metaclass extension since it needs to be overridden at the toolbox in any event. Is that observation correct?
I'm not sure what you mean.
Indeed, we ran a test <Profile>::<Sterotype> is directly defined as a Class (and ONLY a Class)
...
and yet, if we define the toolbox entry as <Profile>::<Sterotype>(UML::Activity), we will get an Activity. This also smells.
No, that's good. An activity IS A[1] class. So in that case EA should be looking for the extension of Activity and instead finding the extension of its superclass.
[1] Via inheritance. Activity IS A Behavior IS A Class.
-
No, that's good. An activity IS A[1] class. So in that case EA should be looking for the extension of Activity and instead finding the extension of its superclass.
[1] Via inheritance. Activity IS A Behavior IS A Class.
If that's the case,
why did
<AppliesTo>
<Apply type="Activity"/>
<Apply type="Class"/>
</AppliesTo>
fail? Remember, the toolbox item was explicitly defined as a Class. It should have found the Class in the antecedent as both Activity and Class are Classes (shades of the Oranges and Lemons problem....)
-
The rule is that as soon as there are multiple extensions in the inheritance hierarchy, specifying the base UML type becomes compulsory.
If a single metaclass is extended then that metaclass can be inferred to be the base type. That doesn't mean that specialized base types aren't valid, just that a logical choice can be made.
As soon as multiple metaclasses exist, even when they are related, the base type can't be inferred so it needs to be manually specified.
-
In the defect report and subsequent investigation by Sparx with respect to decoration inheritance, it was admitted that (at the time - and apparently as of the date of this post with build 1559) such inheritance only worked for one level. That is, one couldn't have a more formal inheritance tree.
Can any Sparxians enlighten us if this is being worked on? I think it was admitted as a defect - and for my money - an important one to get fixed.
We're looking at how to reduce the amount of rework (due to technical, architectural and conceptual debt) we might have when that functionality works as we'd expect and our significant jury-rigged solutions can be greatly simplified.
TIA,
Paolo
BTW: I can't recall if Shape Main (and other Shapes) were inherited through a tree. Perhaps that could be confirmed or denied...
[Edit: If you're looking at Inheritance, then the USDP Inheritance issue (Can <DiagramProperties> be inherited? (https://www.sparxsystems.com/forums/smf/index.php/topic,44825.msg263928.html#msg263928)) would also be good to get sorted.]
-
And what about setting multiple stereotypes? To my experience the order of how the scipts are applied seems random.
q.
-
And what about setting multiple stereotypes? To my experience, the order of how the scripts are applied seems random.
q.
My understanding (from what Eve has said - she can correct me) is that shapes are overwritten, whereas decorations are inherited. Now, since decorations are bound to a compass point, they are, essentially, independent (although I guess we try to set them up so that they don't overwrite each other).
Paolo