Shapescripts in Enterprise Architect are used to define the presentation of elements on a diagram. They are mostly used when defining a UML profile in Enterprise Architect that extends UML or another modelling language with project specific elements and properties.
When developing UML profiles these shapescripts are stored in the _image attribute on the stereotype element, an they can be easily edited using the profile helper.
After a while however you’ll have a bunch of shapescripts scattered over different profiles, and projects, and it becomes hard to manage, or do any kind of version control. Finding a specific shapescript where you used a particular feature is next to impossible if you don’t remember exactly which stereotype this shapescript belonged to.
With the shapescript editor you can export each shapescript individually, but once you have more then a couple of shapescripts that quickly becomes a drag to save your shapescripts to files.
So I wrote a script called ExportAllShapeScripts that searches a repository for all stereotypes that have a shapescript, and exports all of these shapescripts in one go.
This script is part of the Enterprise-Architect-VBScript-Library. Read the article How to use the Enterprise Architect VBScript Library for instructions on downloading and using the Library in Enterprise Architect.
Running this script will save each shapescript as a textfile with extension .shapeScript, grouped in packages per profile.
The code explained
The export script first uses an SQL query to find all shapescripts. Technically the shapescripts are stored in the default property of the attribute with the name _image. The script is stored as an xml tag Image in a zipped and base64 encoded format. A typical shapescript might look like this in the database:
<br /> <Image type="EAShapeScript 1.0" xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="bin.base64"><br /> UEsDBBQAAAAIABpRIkdk2qflMQIAADIHAAAHABEAc3RyLmRhdFVUDQAHncrmVZ3K5lWdyuZV<br /> jVXJTsMwFJxrkfiHCC5FqsRSaIsQhx44sohKcC5toUihqUjYxb8z8xw3jksLsmIn9sx43vOS<br /> HFMMMccECZ749ogZNrGBL6sbSNn3gQwvKFg+DHmKLfZPcM+eZzIeqFGw76Tk3LPvneNj9JEb<br /> Y8TxayoVHMmML+YLRyqWq8emmxP3ybcmuthDC222OyXS4fpEjjGgxh1rH0OTejP2PbF3whly<br /> frewTw2puDbUcVp5kIM62437XHiPDeyy3FnkCXEuviG5D5YXjxrwvcAV6xluiR7za0qP7YUH<br /> oa6X+E1zWzmOncdObsytcjuiSkpPqa3jZBFBgzFleDU/GcfloW1zhJqeJYxHLM8cK3VY1is5<br /> xLJSGINW+5lo33dGDanMGYMyInYLB+hZLWddtqvUMpv9N8dNHJKnHdVZ4/hoMdtfmNhFPNdv<br /> TmMdZSfGhNEUeAsy02eeRnYyuuZR7GPmp1U66lmODlmkKkwca91jj2zh1+XD6cQe6xjnIcbU<br /> 45gaI2Gb2c3xaSulvR/uWs9ZdX7210SjDCgPq336MxWjQqe53YXagQnPeWa3WXWWtCMLu+WE<br /> GHE8tXiqc1tXXr4hHNKtkR7tgb8YB+U6Ca8V/R+rY7vdsTqm8B/Wsek7VpWvOi9ufXHf39bq<br /> qd70KLvujteaPML9EbQnMvYldKF9MLQbODVGeDvXR76sTsr1uCz/RdLVf2Bgd391yyUlem44<br /> 7bq0RG7jgqfqnHfONr8qbN25f34AUEsBAhcLFAAAAAgAGlEiR2Tap+UxAgAAMgcAAAcACQAA<br /> AAAAAAAAAACAAAAAAHN0ci5kYXRVVAUAB53K5lVQSwUGAAAAAAEAAQA+AAAAZwIAAAAA<br /> </Image><br />
So the SQL selects all attributes owned by a element with stereotype «stereotype» with the name _image that have the tag in their Default field.
<br /> 'get all attributes with name _image that have shapescript in the default field and a parent with stereotype «stereotype»<br /> dim sqlGetShapescriptAttributes<br /> sqlGetShapescriptAttributes = "select a.ID from (t_attribute a " & _<br /> " inner join t_object o on (o.Object_ID = a.Object_ID " & _<br /> " and o.Stereotype = 'stereotype')) " & _<br /> " where a.Name = '_image' " & _<br /> " and a.[Default] like '<Image type=""EAShapeScript" & getWC & "'"<br /> dim shapeScriptAttributes<br /> set shapeScriptAttributes = getAttributesByQuery(sqlGetShapescriptAttributes)<br />
Then we loop the schapescript attributes, decode the shapescript and save it as an individual text file.
<br /> 'loop the shape script attributes<br /> for each shapeScriptAttribute in shapeScriptAttributes<br /> 'get the stereotype<br /> dim stereotype as EA.Element<br /> set stereotype = Repository.GetElementByID(shapeScriptAttribute.ParentID)<br /> dim profile as EA.Package<br /> set profile = findProfilePackage(stereotype)<br /> 'load the resultset in the xml document<br /> dim shapeScript<br /> shapeScript = decodeBase64zippedXML(shapeScriptAttribute.Default,"Image")<br /> if len(shapeScript) > 0 then<br /> dim scriptFile<br /> set scriptFile = New TextFile<br /> scriptfile.Contents = shapeScript<br /> 'save the script<br /> scriptFile.FullPath = selectedFolder.FullPath & "\" & profile.Name & "\" & stereotype.Name & ".shapeScript"<br /> scriptFile.Save<br /> 'debug info<br /> Session.Output "saving script: " & scriptFile.FullPath<br /> end if<br /> next<br />
The real difficulty int his script was to decode the shapescript, which is hidden in the method decodeBase64zippedXML defined in the XML utility script. It first base64 decodes the contents of the tag, then saves it as a zip file, unzips the zip file, gets the text file in the zip file, and returns the contents of the text file. Then it deletes the temporary zip file and folder it was extracted to.
If you have shapescripts of your own that you wish to share you can send a github pull request, or an email to firstname.lastname@example.org.
Any bright ideas on how to document each of the shapescripts with an image of shape are welcome too.