[HOWTO] Create Enterprise Architect Stereotype Reference Data using PowerShell

This is a follow-up to the blog post [HOWTO] Convert Images to Enterprise Architect Model Images. As already described there, we wanted to use the official cisco network topology icons (B/W: EPS (7.6 MB) | JPG (4 MB)) in Enterprise Architect to associate them with elements. The import of the images into Enterprise Architect has already been treated in the last post. Let’s proceed with the next step. As EA supports custom stereotypes that allow to apply a different appearance or characteristic to a basic UML model component or feature, we decided to define such a custom stereotype per image. During definition of such a custom stereotype a shape script can be attached to the stereotype that loads the corresponding image. At the end the stereotype can be assigned to any applicable element in EA. To avoid defining the stereotypes and its shape scripts manually we automated that process by creating stereotype reference data with PowerShell. Like the model images reference data, the stereotypes reference date can also be imported into Enterprise Architect. Below I’ll show you how it works.

The example is based on the following versions of Enterprise Architect and PowerShell.
EA Version: 14.0.1423
PowerShell Version: 5

Script for Creation of Stereotype Reference Data

The following script creates Enterprise Architect stereotypes for every image in the specified directory including creation of shape script per image that loads the corresponding image and writes stereotype data to an XML file.

#Requires -Version 5.0

<#
.SYNOPSIS
    Creates Enterprise Architect stereotypes for every image in the specified directory including creation of shape script per image that loads the corresponding image and writes stereotype data to an XML file.
.DESCRIPTION
    The New-StereotypesForImages script creates Enterprise Architect stereotypes for every image in the specified directory including creation of shape script per image that loads the corresponding image and writes stereotype data to an XML file.

    The script takes three parameters; the path to the directory that contains the images and two optional parameters. One to specify the type the stereotype applies to and one to specify the name of the output file.
    It iterates over all images in the images directory and creates for every image a stereotype with the same name as the image and a shape script that loads the corresponding image.
    At the end the generated XML will be saved to the images directory.
.PARAMETER PathToImagesDirectory
    The path to the directory that contains the images.
.INPUTS
    None
.OUTPUTS
    Enterprise Architect stereotype library file (<PathToImagesDirectory>\<StereotypeLibraryFileName>.xml).
.NOTES
    Version:        1.0
    Author:         Rufer Marc
    Creation Date:  31.10.2018
.EXAMPLE
    # Create Enterprise Architect stereotype for every image in directory C:\PATH\TO\DIRECTORY\WITH\IMAGES and write stereotype data to C:\PATH\TO\DIRECTORY\WITH\IMAGES\stereotype-library.xml
    PS > .\New-StereotypesForImages.ps1 -PathToImagesDirectory C:\PATH\TO\DIRECTORY\WITH\IMAGES;
.EXAMPLE
    # Create Enterprise Architect stereotype for every image in directory C:\PATH\TO\DIRECTORY\WITH\IMAGES that applies to the specified type and write stereotype data to C:\PATH\TO\DIRECTORY\WITH\IMAGES\custom-file-name.xml
    PS > .\New-StereotypesForImages.ps1 -PathToImagesDirectory C:\PATH\TO\DIRECTORY\WITH\IMAGES -AppliesTo "Component" -StereotypeLibraryFileName "custom-file-name.xml";
.EXAMPLE
    # Create Enterprise Architect stereotype for every image in directory C:\PATH\TO\DIRECTORY\WITH\IMAGES and write stereotype data to C:\PATH\TO\DIRECTORY\WITH\IMAGES\custom-file-name.xml
    PS > .\New-StereotypesForImages.ps1 -PathToImagesDirectory C:\PATH\TO\DIRECTORY\WITH\IMAGES -StereotypeLibraryFileName "custom-file-name.xml";
#>

PARAM
(
    [Parameter(Mandatory=$true)]
    [string] $PathToImagesDirectory
    ,
    [Parameter(Mandatory=$false)]
    [string] $AppliesTo = "<all>"
    ,
    [Parameter(Mandatory=$false)]
    [string] $StereotypeLibraryFileName = "stereotype-library.xml"
)

Add-Type -Assembly System.Drawing;
Add-Type -AssemblyName System.Web;

# variables
$xmlVersion = "1.0";
$xmlEncoding = [System.Text.Encoding]::GetEncoding(1252);
$exporter = "EA.25";

# load images
$images = Get-ChildItem -Path $PathToImagesDirectory;

# create XML document
$xmlDoc = [System.Xml.XmlDocument]::new();
$xmlDeclaration = $xmlDoc.CreateXmlDeclaration($xmlVersion, $xmlEncoding.HeaderName, $null);
$null = $xmlDoc.AppendChild($xmlDeclaration);

$rootNode = $xmlDoc.CreateNode("element", "RefData", $null);
$rootNode.SetAttribute("version", $xmlVersion);
$rootNode.SetAttribute("exporter", $exporter);
$null = $xmlDoc.AppendChild($rootNode);

$dataSet = $xmlDoc.CreateNode("element", "DataSet", $null);
$dataSet.SetAttribute("name", "Stereotypes");
$dataSet.SetAttribute("table", "t_stereotypes");
$dataSet.SetAttribute("filter", "Stereotype='#Stereotype#' and AppliesTo='#AppliesTo#'");
$null = $rootNode.AppendChild($dataSet);

foreach ($img in $images)
{
    # check, if file is an image
    try
    {
        $null = [System.Drawing.Bitmap]::FromFile($img.FullName);
    }
    catch
    {
        # ignore files that do not have a valid image format
        continue;
    }

    $dataRow = $xmlDoc.CreateNode("element", "DataRow", $null);

    $column1 = $xmlDoc.CreateNode("element", "Column", $null);
    $column1.SetAttribute("name", "Stereotype");
    $column1.SetAttribute("value", $img.BaseName);

    $column2 = $xmlDoc.CreateNode("element", "Column", $null);
    $column2.SetAttribute("name", "AppliesTo");
    $column2.SetAttribute("value", $AppliesTo);

    $column3 = $xmlDoc.CreateNode("element", "Column", $null);
    $column3.SetAttribute("name", "Description");
    $column3.SetAttribute("value", "");

    $column4 = $xmlDoc.CreateNode("element", "Column", $null);
    $column4.SetAttribute("name", "MFEnabled");
    $column4.SetAttribute("value", "FALSE");

    $shapeScript = "shape main { image(""$img"", 0, 0, 100, 100); }";
    $encodedShapeScript = [System.Web.HttpUtility]::HtmlEncode($shapeScript);
    $style = "<STYLE fill=""-1"" text=""-1"" border=""-1"" groupname="""" type=""script""><SHAPE file=""$encodedShapeScript"" type=""EAShapeScript 1.0"" enabled=""1""/></STYLE>";

    $column5 = $xmlDoc.CreateNode("element", "Column", $null);
    $column5.SetAttribute("name", "Style");
    $column5.SetAttribute("value", $style);

    $null = $dataRow.AppendChild($column1);
    $null = $dataRow.AppendChild($column2);
    $null = $dataRow.AppendChild($column3);
    $null = $dataRow.AppendChild($column4);
    $null = $dataRow.AppendChild($column5);
    $null = $dataSet.AppendChild($dataRow);
}

# initialize XML writer
$xmlWriterSettings = [System.Xml.XmlWriterSettings]::new();
$xmlWriterSettings.Encoding = $xmlEncoding;
$xmlWriterSettings.ConformanceLevel   = [System.Xml.ConformanceLevel]::Document;
$xmlWriterSettings.OmitXmlDeclaration = $false;
$xmlWriterSettings.CloseOutput        = $true;
$xmlWriterSettings.Indent             = $true;
$xmlWriterSettings.IndentChars        = "    ";
$xmlWriterSettings.NewLineHandling    = [System.Xml.NewLineHandling]::Replace;

$path = Join-Path -Path $PathToImagesDirectory -ChildPath $StereotypeLibraryFileName;

$sw = [System.IO.File]::CreateText($path);
$xmlWriter = [System.Xml.XmlWriter]::Create($sw, $xmlWriterSettings);

# save XML
try
{
    $xmlDoc.WriteContentTo($xmlWriter);
}
finally
{
    $xmlWriter.Close();
}

#
# Copyright 2018 d-fens GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

XML Output

The XML created by the above script looks as follows.

<?xml version="1.0" encoding="Windows-1252"?>
<RefData version="1.0" exporter="EA.25">
    <DataSet name="Stereotypes" table="t_stereotypes" filter="Stereotype='#Stereotype#' and AppliesTo='#AppliesTo#'">
        <DataRow>
            <Column name="Stereotype" value="100baset hub" />
            <Column name="AppliesTo" value="Component" />
            <Column name="Description" value="" />
            <Column name="MFEnabled" value="FALSE" />
            <Column name="Style" value="<STYLE fill="-1" text="-1" border="-1" groupname="" type="script"><SHAPE file="shape main { image("100baset hub.jpg", 0, 0, 100, 100); }" type="EAShapeScript 1.0" enabled="1"/></STYLE>" />
        </DataRow>
        <DataRow>
            <Column name="Stereotype" value="10GE_FCoE" />
            <Column name="AppliesTo" value="Component" />
            <Column name="Description" value="" />
            <Column name="MFEnabled" value="FALSE" />
            <Column name="Style" value="<STYLE fill="-1" text="-1" border="-1" groupname="" type="script"><SHAPE file="shape main { image("10GE_FCoE.jpg", 0, 0, 100, 100); }" type="EAShapeScript 1.0" enabled="1"/></STYLE>" />
        </DataRow>
        <DataRow>
            <Column name="Stereotype" value="3174 (desktop)" />
            <Column name="AppliesTo" value="Component" />
            <Column name="Description" value="" />
            <Column name="MFEnabled" value="FALSE" />
            <Column name="Style" value="<STYLE fill="-1" text="-1" border="-1" groupname="" type="script"><SHAPE file="shape main { image("3174 (desktop).jpg", 0, 0, 100, 100); }" type="EAShapeScript 1.0" enabled="1"/></STYLE>" />
        </DataRow>
        <DataRow>
            <Column name="Stereotype" value="3x74 (floor)" />
            <Column name="AppliesTo" value="Component" />
            <Column name="Description" value="" />
            <Column name="MFEnabled" value="FALSE" />
            <Column name="Style" value="<STYLE fill="-1" text="-1" border="-1" groupname="" type="script"><SHAPE file="shape main { image("3x74 (floor).jpg", 0, 0, 100, 100); }" type="EAShapeScript 1.0" enabled="1"/></STYLE>" />
        </DataRow>
    </DataSet>
</RefData>

Import Stereotype Ref Data into Enterprise Architect

Stereotype reference data can then be imported into EA as follows. But before importing the stereotype reference data make sure the images that get loaded by the stereotypes already got imported to Enterprise Architect (for details concerning model images reference datea import see [HOWTO] Convert Images to Enterprise Architect Model Images)

  1. Open Enterprise Architect
  2. Open the Enterprise Architect project the model images reference data got imported into
  3. Navigate to Configure tab
  4. Click on Transfer and select Import Reference Data...
  5. Click Select File button on the top right corner and browse for the XML file that contains the before created stereotype data, which is located in the same directory as the images
  6. Click Import
  7. To verify and manage stereotypes enter Stereotype in Find Command... search box and select UML Types

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: