Sparx Systems Forum
Enterprise Architect => Automation Interface, Add-Ins and Tools => Topic started by: Modesto Vega on January 26, 2019, 02:46:52 am
-
I am writing a transform template and have 2 questions:
1) how to remove the suffix of a name.
The following code works
%if elemType != "Class" and elemType != "Interface" and elemType != "Enumeration"%
%endTemplate%
%elemType%
{
%TRANSFORM_REFERENCE("Class")%
stereotype = "Blah"
name=%qt%%CONVERT_NAME(className, "Underscored", "Ht( )Ht")%%qt%
}
%list="Connector" @separator="\n"%
But the code I really need is but it throws an error on name=%qt%%REPLACE(className, "_oplog", " ")%%qt%
%if elemType != "Class" and elemType != "Interface" and elemType != "Enumeration"%
%endTemplate%
%elemType%
{
%TRANSFORM_REFERENCE("Class")%
stereotype = "Logical Data Entity"
name=%qt%%REPLACE(className, "_oplog", " ")%%qt%
name=%qt%%CONVERT_NAME(className, "Underscored", "Ht( )Ht")%%qt%
}
%list="Connector" @separator="\n"%
2) What transform do I need to write to create a relationship between what is being transform and the transformation result - i.e., between the class being transformed and the class resulting from the transformation.
-
1) The only odd thing I see is that you're generating a name twice. I suspect you want something like this
$name=%REPLACE(className, "_oplog", " ")%
name=%qt%%CONVERT_NAME($name, "Underscored", "Ht( )Ht")%%qt%
2) https://sparxsystems.com/enterprise_architect_user_guide/14.0/model_domains/transform_connectors.html (https://sparxsystems.com/enterprise_architect_user_guide/14.0/model_domains/transform_connectors.html)
This script creates a Dependency from a Class created in a transformation, to the Class it was transformed from:
Dependency
{
%TRANSFORM_REFERENCE("SourceDependency",classGUID)%
stereotype="transformedFrom"
Source
{
%TRANSFORM_REFERENCE("Class",classGUID)%
}
Target
{
GUID=%qt%%classGUID%%qt%
}
}
-
1) The only odd thing I see is that you're generating a name twice. I suspect you want something like this
$name=%REPLACE(className, "_oplog", " ")%
name=%qt%%CONVERT_NAME($name, "Underscored", "Ht( )Ht")%%qt%
This is indeed what I am trying to do but I am still getting an error, the error reads:
There was an error parsing on line [nn].
Unexpected symbol: [class name] - "_oplog"
It is weird, it appears as if $name=%REPLACE(className, "_oplog", " ")%
works as expected but name=%qt%%CONVERT_NAME($name, "Underscored", "Ht( )Ht")%%qt%
fails.
I must be missing something obvious.
-
My mistake, I ended up with
$name = %qt%%REPLACE(className, "_oplog", "")%%qt%
name=%CONVERT_NAME($name, "Underscored", "Ht( )Ht")%
Instead of
$name=%REPLACE(className, "_oplog", " ")%
name=%qt%%CONVERT_NAME($name, "Underscored", "Ht( )Ht")%%qt%
Sparx EA does not like this at all.
I do have a 3 additional questions:
1) Is there are online reference on how this very Sparxish language is supposed to work?
I have written an Attribute transformation, it works fine but:
2) how can I transform the attribute stereotype or remove it altogether?
3) can I write a statement like:
$name = %qt%%CONVERT_NAME($name, "Underscored", "Ht( )Ht")%%qt%
if $name contains "id" replace "id" with "ID"
if $name="Oid" then replace "Old" with "OID"
and so on
-
1) Look for transform templates and code generation templates in the help.
2) Add "stereotype" to the TRANSFORM_CURRENT. Each argument added prevents it from copying the original value for that field.
%TRANSFORM_CURRENT("scope","type","stereotype")%
3)Yes, you can do a replace on the result of a previous one. (btw. Did you want to repliace _oplog with a space, or did you want to remove it?)
$name=%REPLACE(className, "_oplog", "")%
$name=%REPLACE($name, "id", "ID")%
$name=%REPLACE($name, "Oid", "OID")%
-
This works nicely :). Thank you for the tips.
I have noticed the following behaviour: if I transform a class with a transformation template and later change/tweak the transformation template, when I transform again a class that has been transformed before Sparx EA updates correctly the class resulting from the previous transformation. Is this intended functionality or one of the many undocumented things Sparx EA does?
-
In your template you have %TRANSFORM_REFERENCE("Class")%. That generates the binding so that synchronization can occur. EA doesn't care if changes are because of the template changing or the original class changing.
-
Sorry to bring this topic back to the top of the forum. I have been writing some transformations with a colleague and everything works fine except for the usual annoying problem.
We have the following model structure:
Model (root)
----A(package)
--------B (package)
We have written a template to transform B (or individual elements in package B) into package C, with "C" being the package name specific in the "File" macro.
Model (root)
----A(package)
--------B (package)
--------C (transformed package)
The elements are transformed correctly but whatever we do, we always end up with wrong package structure, we end up with
Model (root)
----A(package)
--------B (package)
--------C (package)
-----------B (transformed package)
To sum up the second B package is redundant.
Code on the "File" macro
Package
{
name="C"
%list="Namespace" @separator="\n\n" @indent=" "%
}
Code in the "Namespace" macro
%if packagePath == ""%
%list="Class" @separator="\n"%
%endTemplate%
Package
{
%TRANSFORM_CURRENT()%
%list="Class" @separator="\n" @indent=" "%
}
-
If you don't want the origin namespace generated, don't create one in your Namespace template.
%list="Class" @separator="\n"%
Or, if there's any chance your source could contain a deeper structure in the future...
%if packagePath == ""%
%list="Class" @separator="\n"%
%endTemplate%
%list="Namespace" @separator="\n\n" @indent=""%
%list="Class" @separator="\n" @indent=""%
-
Or, if there's any chance your source could contain a deeper structure in the future...
%if packagePath == ""%
%list="Class" @separator="\n"%
%endTemplate%
%list="Namespace" @separator="\n\n" @indent=""%
%list="Class" @separator="\n" @indent=""%
This code in our Namespace works without a deeper structure but does not work with a deeper package structure. It transforms
Model (root)
----A(package)
--------B (package)
Correctly into (with "C" being the package name specific in the "File" macro).
Model (root)
----A(package)
--------B (package)
--------C (transformed package)
But does not transform
Model (root)
----A(package)
--------B (package)
----------B1 (package)
------------B1a (package)
------------B1b (package)
-
One other question, is it possible to write a transform for the Class macro that checks if a class has attributes and transform it only, and only if, it has attributes?
-
This code in our Namespace works without a deeper structure but does not work with a deeper package structure.
Sorry, you need to list child namespaces in the empty packagePath option too, which means there's no conditional behavior at all.
%list="Namespace" @separator="\n\n" @indent=""%
%list="Class" @separator="\n" @indent=""%
One other question, is it possible to write a transform for the Class macro that checks if a class has attributes and transform it only, and only if, it has attributes?
Put this at the top of your class template.
$atts=%list="Attribute" @separator="\n" @indent=" "%
%if $atts==""%
%endTemplate%
-
Put this at the top of your class template.
$atts=%list="Attribute" @separator="\n" @indent=" "%
%if $atts==""%
%endTemplate%
This works fine, thanks for your help.
Sorry, you need to list child namespaces in the empty packagePath option too, which means there's no conditional behavior at all.
%list="Namespace" @separator="\n\n" @indent=""%
%list="Class" @separator="\n" @indent=""%
I don't understand this, the following namespace code variations do not transform sub-packages
%if packagePath == ""%
%list="Namespace" @separator="\n\n" @indent=""%
%list="Class" @separator="\n" @indent=""%
%endTemplate%
%list="Namespace" @separator="\n\n" @indent=""%
%list="Class" @separator="\n" @indent=""%
%if packagePath != ""%
%list="Namespace" @separator="\n\n" @indent=""%
%list="Class" @separator="\n" @indent=""%
%endTemplate%
%list="Namespace" @separator="\n\n" @indent=""%
%list="Class" @separator="\n" @indent=""%
-
If you're wanting to generate a flat copy of the contents of nested namespaces, copy the ddl templates.
FilePackage
{
name="DDL"
namespaceroot="true"
%list="Namespace" @separator="\n\n" @indent=" "%
}
Namespace%list="Namespace" @separator="\n\n"%
%list="Class" @separator="\n\n"%
If you're wanting to include the packages, just not the first one. Go back to the starting namespace template and mark that top package as a namespace root.
-
Almost there, this is a bit more painful than expected. The following code works, it creates a more complex package structure in almost all cases as long as "Include child packages" is specified in the dialog - please not the emphasis as this is very important.
File
%list="Namespace" @separator="\n\n"%
%list="Class" @separator="\n\n"%
Namespace
$transformedPkgNm = %REPLACE(packageName, "P", "L")%
Package
{
namespaceroot="true"
name = %qt%$transformedPkgNm%qt%
%list="Namespace" @separator="\n\n"%
%list="Class" @separator="\n\n"%
}
There 2 things that need addressing and something I do not understand:
- namespaceroot="true" does not appear to do anything, we get the same behaviour in both v13 and v15
- the transform appears to behave differently in v13 and v15, in v13 it works fine but in v15 it also transforms the parent package - i.e., no matter what we do in v15 transformation p2 on a model\p1\p2 structure always copies p1 but in v13 it does not.
- somehow I was expecting to be able to create a (traceability) matrix but I cannot which is leading me to think that a Trace is not created between original and transform elements (I am not referring to the Trace functionality under Design in the ribbon).
-
Sure. If you don't select to include elements in child packages they won't be included.
1. Namespace root isn't something you set via a transform. https://www.sparxsystems.com/enterprise_architect_user_guide/15.0/model_domains/namespaces.html (https://www.sparxsystems.com/enterprise_architect_user_guide/15.0/model_domains/namespaces.html)
2. That's what the check for an empty packagePath is for in the templates.
3. There's an example of creating a connector from the source element to the target in the help. https://www.sparxsystems.com/enterprise_architect_user_guide/15.0/model_domains/transform_connectors.html (https://www.sparxsystems.com/enterprise_architect_user_guide/15.0/model_domains/transform_connectors.html)
-
The namespace was just an inconvenient distraction.
[SNIP]
3. There's an example of creating a connector from the source element to the target in the help. https://www.sparxsystems.com/enterprise_architect_user_guide/15.0/model_domains/transform_connectors.html (https://www.sparxsystems.com/enterprise_architect_user_guide/15.0/model_domains/transform_connectors.html)
Just to clarify what we are trying to do. We have class A and class B connected by an association. I want to
- Transform class A into class A1, class B into class B1, and the association (this works fine)
- Create a trace, which I understand is an Abstraction, between class A and class A1, and another between class B and class B1. None of the examples above work, the problem appears to be that although we have the right source GUID (not transformed) we cannot get the GUID of the transform class to create the connector.
This code works
$Comment="Copy existing connectors (only interested in Associations and Generalisations"
%if connectorType=="Generalization"%
Generalization
{
%TRANSFORM_CURRENT("name","note","alias", "direction", "stereotype")%
%TRANSFORM_REFERENCE(connectorType,connectorGUID)%
Target
{
%TRANSFORM_REFERENCE(connectorDestElemName,connectorDestElemGUID)%
%TRANSFORM_CURRENT("name", "stereotype", "direction")%
}
Source
{
%TRANSFORM_REFERENCE(connectorSourceElemName,connectorSourceElemGUID)%
%TRANSFORM_CURRENT("name", "stereotype", "direction")%
}
}
%endIf%
%if connectorType=="Association"%
Association
{
%TRANSFORM_CURRENT("name","note","alias", "direction", "stereotype")%
%TRANSFORM_REFERENCE(connectorType,connectorGUID)%
Source
{
%TRANSFORM_REFERENCE(connectorDestElemName,connectorDestElemGUID)%
%TRANSFORM_CURRENT("name", "stereotype", "direction")%
multiplicity=%qt%%connectorDestMultiplicity%%qt%
}
Target
{
%TRANSFORM_REFERENCE(connectorSourceElemName,connectorSourceElemGUID)%
%TRANSFORM_CURRENT("name", "stereotype", "direction")%
multiplicity=%qt%%connectorSourceMultiplicity%%qt%
}
}
%endIf%
-
Connecting to a Class for which you know the GUID
The second type of Class that you can use as a connector end is an existing element for which you know the current GUID. To create this connection, specify the GUID of the target Class in either the source or target end; this script creates a Dependency from a Class created in a transformation, to the Class it was transformed from:
Dependency
{
%TRANSFORM_REFERENCE("SourceDependency",classGUID)%
stereotype="transformedFrom"
Source
{
%TRANSFORM_REFERENCE("Class",classGUID)%
}
Target
{
GUID=%qt%%classGUID%%qt%
}
}
-
Connecting to a Class for which you know the GUID
The second type of Class that you can use as a connector end is an existing element for which you know the current GUID. To create this connection, specify the GUID of the target Class in either the source or target end; this script creates a Dependency from a Class created in a transformation, to the Class it was transformed from:
Dependency
{
%TRANSFORM_REFERENCE("SourceDependency",classGUID)%
stereotype="transformedFrom"
Source
{
%TRANSFORM_REFERENCE("Class",classGUID)%
}
Target
{
GUID=%qt%%classGUID%%qt%
}
}
Unless I had a senior moment yesterday, not impossible considering the day I had, that in the Connector macro didn’t work and I don’t understand why. A debug reveals that the transform tries to create a relationship to itself.
The only thing we haven’t try is putting that in the Class macro.
-
The meaning of the word, Help, is very important. Unhelpful Help is no help.
The following code in the official Help is wrong:
Connecting to a Class for which you know the GUID
The second type of Class that you can use as a connector end is an existing element for which you know the current GUID. To create this connection, specify the GUID of the target Class in either the source or target end; this script creates a Dependency from a Class created in a transformation, to the Class it was transformed from:
Dependency
{
%TRANSFORM_REFERENCE("SourceDependency",classGUID)%
stereotype="transformedFrom"
Source
{
%TRANSFORM_REFERENCE("Class",classGUID)%
}
Target
{
GUID=%qt%%classGUID%%qt%
}
}
The following code works (the subtle but maddening difference is connectorSourceElemGUID instead of classGUID in the TRANSFORM_REFERENCE command)
Abstraction
{
%TRANSFORM_REFERENCE("SourceDependency",connectorSourceElemGUID)%
stereotype="trace"
Source
{
%TRANSFORM_REFERENCE(className,connectorSourceElemGUID)%
}
Target
{
GUID=%qt%%classGUID%%qt%
}
}
-
It says classGUID because it can be added to the Class template.
If you add it to a connector template and use connectorSourceElemGUID instead you'll probably generate the connector multiple times (although EA won't create multiple connectors if you have the transform reference for the connector) but you'll also not generate the trace for elements with no outgoing connectors.
-
[SNIP]
It says classGUID because it can be added to the Class template.
Please provide a working example of that code in the Class template. We cannot get that code, the code in the help working anywhere.
[SNIP]
If you add it to a connector template and use connectorSourceElemGUID instead you'll probably generate the connector multiple times (although EA won't create multiple connectors if you have the transform reference for the connector) but you'll also not generate the trace for elements with no outgoing connectors.
v13 does not generate multiple connectors, it only generates 1 connector.
-
[SNIP]
It says classGUID because it can be added to the Class template.
Please provide a working example of that code in the Class template. We cannot get that code, the code in the help working anywhere.
A working example of the code in the Class template is:
Class
{
%TRANSFORM_REFERENCE(className, classGUID)%
%TRANSFORM_CURRENT("stereotype")%
stereotype="A Stereotype"
Abstraction
{
%TRANSFORM_REFERENCE("SourceDependency",classGUID)%
stereotype="trace"
Source
{
%TRANSFORM_REFERENCE(className,classGUID)%
}
Target
{
GUID=%qt%%classGUID%%qt%
}
}
%list="Attribute"%
}
%list="Connector" @separator="\n"%
Anywhere else in the template, the code would give an error. Could somebody please update the help?
-
%elemType%
{
%TRANSFORM_REFERENCE("Class")%
%TRANSFORM_CURRENT()%
}
Dependency
{
%TRANSFORM_REFERENCE("SourceDependency",classGUID)%
stereotype="transformedFrom"
Source
{
%TRANSFORM_REFERENCE("Class",classGUID)%
}
Target
{
GUID=%qt%%classGUID%%qt%
}
}
Drop the transformed element and the original onto the same diagram and you will see a stereotyped dependency between them.
-
Thanks Eve, the code in you last post also works fine as long as we add %list="Connector" @separator="\n"% at the end to trigger a transformation of connectors.
Just for clarity what is the difference between these 2 syntax:
Class {}
and
%elemType% {
%TRANSFORM_REFERENCE("Class")%
%TRANSFORM_CURRENT()%
}
Something I have also notice is that it appears there is a 1-to-1 relationship between a transformation template and a target folder. Once a target folder has been specified we do not seem to be able to execute the same transform against a different target folder.
-
%elemType% will evaluate to Class if you are transforming a class.
%TRANSFORM_REFERENCE("Class")% creates a reference that allows synchronization of transforms, linking etc. See the help for more details.
%TRANSFORM_CURRENT()% copies fields from the original element into the new one.
Yes, I removed all the extra lists from my class template for brevity.
EA remembers the target packages for particular elements. If you generate the same transform for the same elements a second time it will then synchronize with the previous elements instead of creating new ones.
-
[SNIP]
EA remembers the target packages for particular elements. If you generate the same transform for the same elements a second time it will then synchronize with the previous elements instead of creating new ones.
Have I understood you correctly?
Let's say I have package A and element E1 and we transform E1 into package B (with the resulting element being E1(b), once element E1 has been transformed into E1(b)) in Package B the source element cannot be transformed into Package C, to create. element E1(c)?
What would happen if we psychically duplicated the transformation template and gave it a different name but use the same code?
-
Yes, you understand.
The key though is the TRANSFORM_REFERENCE macro. (See https://www.sparxsystems.com/enterprise_architect_user_guide/15.0/model_domains/crossreferences2.html (https://www.sparxsystems.com/enterprise_architect_user_guide/15.0/model_domains/crossreferences2.html))
Its purpose is to create a unique id for referencing a transformed class based on the source class. I can create an arbitrary number of elements from a single source element in the one transform. Usually I'll do that by changing the name. I can also create connectors in any combination between those elements by specifying the same 3 values in the transform reference to each end of a connector. When processing a connector you can again create 0..* connectors linking different combinations of the transform results for the source and target relationships. I can even link to the result of a completely different transform.
But all that does rely on creating a unique identifier for each transformed elements.
If you copy your entire transform, the default third parameter will change and you will get a new set of elements.
-
Thanks Eve, I think I get the gist of it. Hopefully, one final question. Where in the repository at the transform references stored? In the xref tables?
-
I'm afraid I can't remember that detail.
Turn auditing on to its highest setting, run a transform of a single item then look at the raw log.
-
Sorry to resurrect this topic but I got a transform giving me a headache.
I have reverse engineered a physical database using Database Builder and Sparx 15.1.1527. I have a physical to logical transform that I thought worked fine in previous version of Sparx but in this case it does not do 2 things:
- it does not generate a trace between the physical and logical data entities
- most importantly, it does not transform/copy any foreign keys.
Where have I gone wrong?
Latest Class transform is
$COMMENT=" The class template is used for all elements along with the "
$COMMENT=" class macros. This template copies all class information "
$COMMENT=" including everything that the class contains. "
$COMMENT=" A %TRANSFORM_REFERENCE()% macro call is required to "
$COMMENT=" identify the transformed class. "
%if elemType != "Class" and elemType != "Interface" and elemType != "Enumeration"%
%endTemplate%
%elemType%
{
%TRANSFORM_REFERENCE("Class")%
stereotype = "Logical Data Entity"
language = "Canonical"
%list="Attribute" @separator="\n" @indent=" "%
$name=%REPLACE(className, "tbl_", "")%
$name=%REPLACE(className, "tbl", "")%
name=%qt%%CONVERT_NAME($name, "Pascal Case", "Ht( )Ht")%%qt%
%list="Connector" @separator="\n"%
Abstraction
{
%TRANSFORM_REFERENCE("SourceDependency",classGUID)%
stereotype="trace"
Source
{
%TRANSFORM_REFERENCE(className,classGUID)%
}
Target
{
GUID=%qt%%classGUID%%qt%
}
}
}
Latest Connector transform is (copied from the Data Modelling to ERD transform, as the previous one is not working)
$Comment="Convert the links between Entities to Associations."
%if connectorType=="Association"%
Association
{
%TRANSFORM_CURRENT("name","note","alias","direction", "stereotype")%
%TRANSFORM_REFERENCE("ERDRelationship",connectorGUID)%
stereotype="ERD_Relationship"
Source
{
%TRANSFORM_REFERENCE(connectorDestElemName,connectorDestElemGUID)%
%TRANSFORM_CURRENT("name", "stereotype","direction")%
multiplicity=%qt%%connectorDestMultiplicity%%qt%
}
Target
{
%TRANSFORM_REFERENCE(connectorSourceElemName,connectorSourceElemGUID)%
%TRANSFORM_CURRENT("name", "stereotype","direction")%
multiplicity=%qt%%connectorSourceMultiplicity%%qt%
}
}
%endIf%
-
I was hoping to have gotten a reply on this already. The Data Modelling to ERD transform does not have this problem and I suspect that there is something in that transformation that should be in the Physical to Logical Transformation. I also suspect that this may have something to do with Sparx v15, since, from memory, I do recall having a similar problem with a similar transformation on Sparx EA v 14.