Sparx Systems Forum
Enterprise Architect => Suggestions and Requests => Topic started by: bmantuano on June 18, 2008, 10:54:41 am
-
Being able to transform from a PSM back to a PIM would be a nice feature to have, particularly when starting from an existing codebase.
Perhaps there's already a way to do this already?? - without writing a custom transform.
-
It is possible (I've done it personally) but you do need to write a custom transformation.
-
Thanks for the reply, Simon. Ugh. That was my suspicion. I'll take a stab at it, but I'll admit I'm a little scared :0
-
Recognize that there is an inherent problem about moving in the reverse direction since you are trying to move from concrete to abstract and the intent and purpose information which are part of the abstract model are only indirectly reflected in the concrete model. So, it really depends on what kind of transformation you are trying to undo. Some are likely to be pretty straightforward, but others are likely to be quite difficult. Of course, if one knew what the forward transformation was, then reversing it would be far easier ... but if one knew that, then one should also have the more abstract end of the model anyway. Of course, if you have unruly programmers fiddling with the generated code, you might have the model out of sync!
-
Thomas is spot on. Going more abstract is much harder than the other way around.
My advice is to not be afraid of calling an add-in from the templates to help. My transformation involved using information from two matching classes to make a single class. I used an add-in to look up the relevant information from the second class, among other things.
-
Thank you both for the guidance.
I agree it's less than the ideal workflow. Ideally we'd have started with a PIM and developed off of that. Due to time constraints and so forth, we took more of an ad-hoc approach so I'm now trying to put together a holistic picture of what we've got so far. I'd imagine this is a common scenario, no?
Anyhow, I'm trying my luck with the transforms based on the existing ones.
Just to give some background, I'm trying to take an AS3 PSM and turn it into something like what is shown here:
http://www.onflex.org/ted/2006/10/cube-wallpaper-as3-and-flex-api.php.
- essentially removing the individual property getter and setter entries with one attribute-esque entry.
Thanks again for your help so far. If you've got any other suggestions, please pass em my way :)
-
If you're model already includes the attribute, you can start by filtering the operations list.
%list="Operation" @separator="\n" @indent=" " opStereotype!="property get" and opStereotype!="property set"%
Either way, from the Attribute or Operation templates you could work out what the various other things should look like and do a list (Custom template that just outputs something constant) to see if they exist. This will allow you to control aspects of what gets generated without needing to ask an add-in.
-
Ok thanks. That helps. I've been making some progress :) I can create attributes from the property getters/setters and I can hide the original operations using the code you put up. I'm naturally getting duplicate attributes, but I'm much more hopeful now.
-
Great, the second part of my post suggests how you can get rid of the duplicate.
Here's something a little more concrete. When transforming your set property, work out the name of the matching get property. Do a list specifying that the name matches that (there's a certain side you have to put the variable on, but I can't remember off the top of my head.)
If that list returns an empty string there is no setter and you need to create the attribute. If it returns something then you don't need to create the attribute. You can do a similar trick to mark the attribute as readonly, but you'll need to use a custom template because otherwise you'll end up with infinite recursion in your templates.
-
Hi Simon,
I think I've figured out lists :). But I believe I've got a problem referencing the transformation in progress vs. the original class.
Here's a snippet of what I've got so far. The basic idea follows your suggestion and checks whether an attribute already exists (via the list). Only if it doesn't exist, will it be created.
$attributes=%TRANSFORM_REFERENCE%%list="Attribute" @separator=", " attName==$propertyName%
%if opStereotype=="property set" or opStereotype=="property get"%
%if $attributes == ""%
Attribute {
%TRANSFORM_REFERENCE()%
name=%qt%$propertyName%qt%
stereotype="property"
scope="Public"
type=%qt%$type%qt%
Tag{name="attribute_name" value=%qt%$attName%qt%}
}
%endIf%
%endIf%
I'm guessing that the list is being created from the original class and so it's always empty since it never had those attributes.
Any suggestions for this?
-
I don't think you've quite understood me. So here's an example.
First, a template that I can list over just to see if an operation exists.
Operation__Exists Template T
Now a stereotype override for «property set» that generates the attribute if the matching «property get» doesn't exist.
Operation Template «property set» Stereotype Override $prefix=%LEFT(opName,3)%
$rest=%MID(opName,3)%
%if $prefix != "set"%
%endTemplate%
$getName = "get" + $rest
$exists=%list="Operation__Exists" @separator="" @indent="" $getName==opName%
%if $exists==""%
Attribute
{
name=%qt%$rest%qt%
type=%qt%%opReturnType%%qt%
Tag
{
name="writeonly"
value="true"
}
}
%endIf%
Finally, a stereotype override for «property get». It will generate the attribute but mark it as readonly if no «property set» is found.
Operation Template «property get» Stereotype Override $prefix=%LEFT(opName,3)%
$rest=%MID(opName,3)%
%if $prefix != "get"%
%endTemplate%
Attribute
{
name=%qt%$rest%qt%
type=%qt%%opReturnType%%qt%
$setName = "set" + $rest
$exists=%list="Operation__Exists" @separator="" @indent="" $setName==opName%
%if $exists==""%
Tag
{
name="readonly"
value="true"
}
%endIf%
}
There are plenty of ways to generalize this, but the way it works is sound.
-
Thanks so much for your help, Simon. I managed to get it working!
Yeah, I had a different approach. I was trying to take different paths depending on whether an action had already taken place instead of the type of Operation being evaluated.
One thing I saw in your list code was "$setName==opName" which is surprisingly different than "opName==$setName" which is what I was trying to do earlier. I had to double-check that one, but indeed they result in two different transformations. By design?
-
As I said earlier, you have to be careful which side of the operator you put the variable on. The left side is evaluated in the current template, the right is evaluated in the template being executed for the list.
-
Ok, I see. That'll take some getting used to but I see the idea now.
Simon, one more question for you:
How do you obtain a list of the arguments for a given Operation? I looked at all the Field Substitution Macros and found everything BUT a way to get the arguments. opArguments??
I saw there's a paramType which looks promising, but I don't understand how you can get context.
-
Another recommendation for the next release: More documentation on the transform language. Maybe would keep me from bugging you so much Simon :)
One thing in particular that took me a while to figure out was some of the reserved words. For example, the "Initial" value of an attribute is modified via the keyword "default". While I managed to eventually find this under the docs, it was only through trial and error that I figured out that the keyword "constant" is used to control the "Const" attribute - NOT "IsConst" as the documentation suggests.
-
Try listing the parameters of the operation.
Here's the list for what can be genererated in a transform. http://www.sparxsystems.com.au/EAUserGuide/index.html?transformingobjects.htm
Here's the list of macros for getting values. http://www.sparxsystems.com.au/EAUserGuide/index.html?fieldsubstitutionmacros.htm
Look around those two pages for more information.
-
Another recommendation for the next release: More documentation on the transform language. Maybe would keep me from bugging you so much Simon :)
One thing in particular that took me a while to figure out was some of the reserved words. For example, the "Initial" value of an attribute is modified via the keyword "default". While I managed to eventually find this under the docs, it was only through trial and error that I figured out that the keyword "constant" is used to control the "Const" attribute - NOT "IsConst" as the documentation suggests.
Please report these via a bug report - use the link near the bottom of any forum page.
That way this issue will get directly to Roy's team, who will see that the documentation gets updated.
Thanks much,
David
-
Hi Simon,
Thanks, that worked. I created a list and then called a Parameter template using the list and was able to get context that way.
Midnight,
Thanks for the tip. I'll add it.