Sparx Systems Forum
Enterprise Architect => Automation Interface, Add-Ins and Tools => Topic started by: Modesto Vega on September 17, 2025, 02:15:47 am
-
Trying to get some scripts written to converts element from a UML based MDG to an ArchiMate based MDG.
Let's take What I thought will be a simple example, converting a UML Component with a stereotype of "System" to an ArchiMate "Application Component" - i.e., an element with a stereotype of "ArchiMate_ApplicationComponent".
At first the scripts worked fine but then things got unexpectedly weird.
There are 2 scripts in play:
!INC Local Scripts.EAConstants-JScript
!INC DAF2.daf2_Element_Utilities
/*
* This code has been included from the default Diagram Script template.
* If you wish to modify this template, it is located in the Config\Script Templates
* directory of your EA install path.
*
* Script Name:
* Author:
* Purpose:
* Date:
*/
/*
* Diagram Script main function
*/
function OnDiagramScript()
{
// Get a reference to the current diagram
var currentDiagram as EA.Diagram;
currentDiagram = Repository.GetCurrentDiagram();
if (currentDiagram == null)
{
Session.Output("Please open a diagram and select an element.");
return;
}
else if ( currentDiagram != null )
{
// Get a reference to any selected connector/objects
var selectedObjects as EA.Collection;
selectedObjects = currentDiagram.SelectedObjects;
if (selectedObjects.Count == 0)
{
Session.Output("❌ No elements selected in the diagram.");
return;
}
Session.Output("🔁 Processing selected elements in diagram...");
for (var i = 0; i < selectedObjects.Count; i++)
{
var diagramObject = selectedObjects.GetAt(i);
var element = Repository.GetElementByID(diagramObject.ElementID);
if (element == null)
{
Session.Output("⚠️ Skipping: could not retrieve element at index " + i);
continue;
}
Session.Output("✅ Converting '" + element.Name + "' (Component) → ArchiMate_ApplicationComponent...");
// Use utility function
convertElementType(element, "ArchiMate_ApplicationComponent", "Component");
}
}
currentDiagram.Update();
Session.Output("✅ Conversion complete.");
}
OnDiagramScript();
And
function convertElementType(element, newStereotype, newType)
{
element.Stereotype = newStereotype;
element.Type = newType;
// Clear custom style overrides (optional)
element.StyleEx = "";
element.Update();
}
I thought the original test was successful but I am having my doubts now because the scripts does not change the type or stereotype and must be missing something obvious I cannot see.
-
Don't use .Stereotype. Instead use .StereotypeEx, and pass the fully qualified stereotype.
Geert
-
Here is some code that I used to do something similar but selecting a package in project browser.
https://sparxsystems.com/forums/smf/index.php/topic,45674.msg267977.html#msg267977 (https://sparxsystems.com/forums/smf/index.php/topic,45674.msg267977.html#msg267977)
If you replace the following line
//Convert standards to MDG standard
Conversions[0] = new TypeConversion("Class", "Standard", "Class", "Motivation::Standard");With this line it should convert a UML Component to ArchiMate3::ApplicationComponent
//Convert Component
elementConversions[0] = new TypeConversion( "Component", "","Component", "ArchiMate3::ArchiMate_ApplicationComponent");It should work.
Note that I developed this script further to convert connectors and diagram types however, when I tried to post it I got blocked as I had to use SQL to convert the diagram.
-
Here's my full conversion script:
'[path=\Projects\Project EL\Conversion]
'[group=Conversion]
option explicit
!INC Local Scripts.EAConstants-VBScript
!INC Wrappers.Include
'
' Script Name: Convert Archimate Stereotypes
' Author: Geert Bellekens
' Purpose: Convert ArchiMate Capabilities from standard to GB MDG
' Date: 2023-01-20
'
const outPutName = "Convert Model"
dim stereotypeMapping
set stereotypeMapping = CreateObject("Scripting.Dictionary")
dim taggedValuesMapping
set taggedValuesMapping = CreateObject("Scripting.Dictionary")
dim taggedValuesCopy
set taggedValuesCopy = CreateObject("Scripting.Dictionary")
'----------------CONFIGURATION---------------------------------------
'Stereotypes
'stereotypeMapping.Add "GB Modelling::ArchiMate_BusinessFunction", "GB Modelling::ArchiMate_Capability"
'stereotypeMapping.Add "ArchiMate3::ArchiMate_Capability", "GB Modelling::ArchiMate_Capability"
'stereotypeMapping.Add "ArchiMate3::ArchiMate_BusinessFunction", "GB Modelling::ArchiMate_Capability"
'stereotypeMapping.Add "ArchiMate3::ArchiMate_BusinessObject", "GB Modelling::GB_BIM_Class"
'stereotypeMapping.Add "Class;<null>", "GB Modelling::GB_BIM_Class"
'stereotypeMapping.Add "Attribute;<null>", "GB Modelling::GB_BIM_Attribute"
'stereotypeMapping.Add "Association;<null>", "GB Modelling::GB_BIM_Association"
'stereotypeMapping.Add "Aggregation;<null>", "Association;GB Modelling::GB_BIM_Association"
'stereotypeMapping.Add "GB Modelling::GB_BIM_Association", "Association;GB Modelling::GB_BIM_Association" 'temporary
'stereotypeMapping.Add "Logical;<null>", "GB Modelling::BIM View"
'stereotypeMapping.Add "GB Modelling::BIM View", "GB Modelling::CBIM View" 'temporary
stereotypeMapping.Add "GB Modelling::GB_BIM_Class", "GB Modelling::GB_CBIM_Class"
stereotypeMapping.Add "GB Modelling::GB_BIM_Association", "GB Modelling::GB_CBIM_Association"
'TaggedValues (replace by)
'taggedValuesMapping.Add "Capa Maturity", "Maturity"
'taggedValuesMapping.Add "Capa Level", "Level"
'TaggedValues (copy value to)
'taggedValuesCopy.Add "Maturity", "Maturity 50Hz"
'----------------CONFIGURATION---------------------------------------
sub main
'reset output tab
Repository.CreateOutputTab outPutName
Repository.ClearOutput outPutName
Repository.EnsureOutputVisible outPutName
'report progress
Repository.WriteOutput outPutName, now() & " Starting " & outPutName, 0
'do the actual work
convertCapabilities()
'report progress
Repository.WriteOutput outPutName, now() & " Finished " & outPutName, 0
end sub
function convertCapabilities()
dim package as EA.Package
set package = Repository.GetTreeSelectedPackage
convertPackage package
end function
function convertPackage(package)
'report progress
Repository.WriteOutput outPutName, now() & " Processing '" & package.Name & "'", 0
'convert elements
dim element as EA.Element
for each element in package.Elements
convertElement element, -1
next
'process diagrams
convertDiagrams(package)
'process subPackages
dim subPackage as EA.Package
for each subPackage in package.Packages
convertPackage subPackage
next
end function
function convertElement(element, level)
dim mappingKey
if len(element.FQStereotype) > 0 then
mappingKey = element.FQStereotype
else
mappingKey = element.Type & ";<null>"
end if
dim userMessage
userMessage = " Converting element '" & element.Name & "'"
'Repository.WriteOutput outPutName, now() & " debug before convertItem: " & element.Name, 0
'convert the element
convertItem element, userMessage, mappingKey, level
'Repository.WriteOutput outPutName, now() & " debug after convertItem: " & element.Name, 0
'process attributes
dim attribute as EA.Attribute
for each attribute in element.Attributes
convertAttribute element, attribute
next
'process (outgoing) relations
dim connector as EA.Connector
for each connector in element.Connectors
if connector.ClientID = element.ElementID then
convertConnector element, connector
end if
next
'process diagrams
convertDiagrams(element)
'process subElements
dim subElement as EA.Element
for each subElement in element.Elements
convertElement subElement, level + 1
next
end function
function convertConnector(element, connector)
dim mappingKey
if len(connector.FQStereotype) > 0 then
mappingKey = connector.FQStereotype
else
mappingKey = connector.Type & ";<null>"
end if
dim userMessage
userMessage = " Converting connector '" & element.Name & "." & connector.Name & "'"
'convert the connector
convertItem connector, userMessage, mappingKey, ""
end function
function convertAttribute(element, attribute)
dim mappingKey
if len(attribute.FQStereotype) > 0 then
mappingKey = attribute.FQStereotype
else
mappingKey = "Attribute;<null>"
end if
dim userMessage
userMessage = " Converting attribute '" & element.Name & "." & attribute.Name & "'"
'convert the attribute
convertItem attribute, userMessage, mappingKey, ""
end function
function convertDiagrams(diagramOwner)
dim diagram as EA.Diagram
for each diagram in diagramOwner.Diagrams
'get mapping key
dim mappingKey
if len(diagram.MetaType) > 0 then
mappingKey = diagram.MetaType
else
mappingKey = diagram.Type & ";<null>"
end if
'convert
if stereotypeMapping.Exists(mappingKey) then
'if true then 'temporary for CBIM conversion
Repository.WriteOutput outPutName, now() & " Converting diagram '" & diagram.Name & "'", 0
dim styleEx
'hide connector stereotypes
styleEx = setValueForKey(diagram.StyleEx, "HideConnStereotype", "1")
'set view to empty
styleEx = setValueForKey(styleEx, "MDGView", "")
'disable fully scoped object names
styleEx = setValueForKey(styleEx, "NoFullScope", "1")
dim extendedStyle
'hide attribute stereotypes
extendedStyle = setValueForKey(diagram.ExtendedStyle, "HideStereo", "1")
'hide element stereotypes
extendedStyle = setValueForKey(extendedStyle, "HideEStereo", "1")
diagram.StyleEx = styleEx
diagram.ExtendedStyle = extendedStyle
diagram.MetaType = stereotypeMapping(mappingKey)
'diagram.MetaType = "GB Modelling::CBIM View" 'temporary for CBIM conversion
diagram.Update
end if
next
end function
function convertItem(item, userMessage, mappingKey, level)
if stereotypeMapping.Exists(mappingKey) then
dim tagsDictionary
set tagsDictionary = getTagsDictionary(item)
dim setLevel3
setLevel3 = false
if instr(mappingKey, "ArchiMate_BusinessFunction") > 0 then
setLevel3 = true
end if
'report progress
Repository.WriteOutput outPutName, now() & userMessage, 0
dim dirty
dirty = false
'check if we have a type to convert to
dim mappingTarget
dim targetSteretoype
mappingTarget = stereotypeMapping(mappingKey)
if instr(mappingTarget, ";") > 0 then
'fix the aggregation direction if needed
'aggregation with Direction "Source -> Destination" don't have arrows.
'If we change the type to Association, they do, so we change Direction to Unspecified in order to remove the arrow
if item.ObjectType = otConnector then
if item.Type = "Aggregation" _
and item.Direction = "Source -> Destination" then
item.Direction = "Unspecified"
dirty = true
end if
end if
'get type and stereotype
dim mappingTargetParts
mappingTargetParts = split(mappingTarget, ";")
if item.Type <> mappingTargetParts(0) then
item.Type = mappingTargetParts(0) 'type
dirty = true
end if
targetSteretoype= mappingTargetParts(1)
else
targetSteretoype = mappingTarget
end if
if item.FQStereotype <> targetSteretoype then
item.StereotypeEx = targetSteretoype 'stereotype
dirty = true
end if
if dirty then
item.Update
end if
'Repository.WriteOutput outPutName, now() & " debug after item update: " & item.Name, 0
if setLevel3 then
'convert tagged values
convertTaggedValues item, "3", tagsDictionary
else
'convert tagged values
convertTaggedValues item, level, tagsDictionary
end if
end if
end function
function getTagsDictionary(item)
dim tagsDictionary
set tagsDictionary = createObject("Scripting.Dictionary")
dim tag as EA.TaggedValue
for each tag in item.TaggedValues
if not tagsDictionary.Exists(tag.Name) then
tagsDictionary.Add tag.Name, tag.Value
'Repository.WriteOutput outPutName, now() & " adding tag to dictionary " & tag.Name & " value: " & tag.Value , 0
end if
next
'return
set getTagsDictionary = tagsDictionary
end function
function convertTaggedValues(element, level, tagsDictionary)
'Repository.WriteOutput outPutName, now() & " debug before update existing tags: " & element.Name, 0
dim tag as EA.TaggedValue
element.TaggedValues.Refresh
'Repository.WriteOutput outPutName, now() & " debug after taggedvalues refresh: " & element.Name, 0
'first loop tagged values to copy the pre-existing tag values
for each tag in element.TaggedValues
'Repository.WriteOutput outPutName, now() & " debug processing tag: " & tag.Name & " tagsDictionary.Count: " & tagsDictionary.Count , 0
'check the pre-existing tags and copy their value
if tagsDictionary.Exists(tag.Name) then
'Repository.WriteOutput outPutName, now() & " debug updating tag: " & tag.Name, 0
tag.Value = tagsDictionary(tag.Name)
tag.Update
end if
next
'refresh to make sure we have the correct tags and values
element.TaggedValues.Refresh
'Repository.WriteOutput outPutName, now() & " debug after update existing tags: " & element.Name, 0
'then convert if needed
for each tag in element.TaggedValues
dim convertedTag
'convert tags
if taggedValuesMapping.Exists(tag.Name) then
set convertedTag = getExistingOrNewTaggedValue(element, taggedValuesMapping(tag.Name))
convertedTag.Value = tag.Value
convertedTag.Update
deleteTag element, tag.Name
end if
'copy tag values
if taggedValuesCopy.Exists(tag.Name) then
'Repository.WriteOutput outPutName, now() & " debug tag to copy: " & tag.Name, 0
set convertedTag = getExistingOrNewTaggedValue(element, taggedValuesCopy(tag.Name))
convertedTag.Value = tag.Value
convertedTag.Update
end if
'check level tag
if lcase(tag.Name) = "level" then
dim correctLevel
correctLevel = "L" & level
if not lcase(tag.Value) = lcase(correctLevel) then
if lcase(tag.Value) = "tbd" or len(tag.Value) = 0 then
tag.Value = correctLevel
tag.Update
else
'report issue
Repository.WriteOutput outPutName, now() & " ERROR: Level tag on '" & element.Name & "' with GUID '" & element.ElementGUID & "' is '" & tag.Value & "' and should be '" & correctLevel & "'", 0
end if
end if
end if
next
end function
main
Geert
-
Thank you for both of your contributions. After making changes to the scripts based on a variation of both your contributions, it appears that the new target stereotype gets added to any existing element stereotype and as a result the type gets changed to a "Class".
In other words, using this adds an additional stereotype to the element being converted.
Instead use .StereotypeEx, and pass the fully qualified stereotype.
Somehow, I was expecting this code to do the trick but it does not.
VBScript
if item.FQStereotype <> targetSteretoype then
item.StereotypeEx = targetSteretoype 'stereotype
dirty = true
end if
JScript
var dirty = 0
if (element.FQStereotype != newStereotype)
{
element.StereotypeEx = newStereotype;
dirty = 1
}
It is looking like somehow the existing StereotypeEx needs to be cleared.
Do I need to set element.StereotypeEx to "", update the element, and set the new stereotype?
Please keep in mind that we have not developed the new MDG out, at the moment we are testing how to translate existing content to ArchiMate.
-
Setting stereotypeEx clears all stereotypes and sets it to just one.
If you are thinking of creating an MDG extension to archimate let me know. I have one.
-
Setting stereotypeEx clears all stereotypes and sets it to just one.
I was expecting this but stereotypeEx doesn’t clear the stereotypes.
If you are thinking of creating an MDG extension to archimate let me know. I have one.
We are thinking about creating an MDG extension of ArchiMate. Please feel free to DM me.
-
I've had that problem too in the past, but I don't remember exactly how I solved it.
Might have been something like reloading (using Repository.GetElementByID) the element after setting the stereotype or something.
Geert
-
This gets better by the minute, the script now works fine with or without using using Repository.GetElementByID. The scripts have not changed, only the day has changed, including disconnecting and reconnecting the laptop from the network and logging in without restarting the computer, it even applies the right colour fill.
I am officially happily confused. Only explanation I can think of is that Sparx EA was somehow caching the script.
-
This gets better by the minute, the script now works fine with or without using using Repository.GetElementByID. The scripts have not changed, only the day has changed, including disconnecting and reconnecting the laptop from the network and logging in without restarting the computer, it even applies the right colour fill.
I am officially happily confused. Only explanation I can think of is that Sparx EA was somehow caching the script.
That is indeed a possibility. In some weird conditions I've seen that happen as well.
Geert
-
You can find the model I originally used to create Archimate Extension on GitHub.
https://github.com/EASunshine/Sparx-EA/ (https://github.com/EASunshine/Sparx-EA/)
Download the file EAMDGProfile.zip - Has Full EA Model and files, icons etc to create a ArchiMate MDG Extension.
Instructions on how to build the MDG can be found in model.
If I get time over the weekend I'll update it. Found I needed to restructure it so it worked with Prolaborate. For now that should give you a good start at creating your own.
Used this at several organisations successfully to manage large transformations.