sqlsqliteenterprise-architect

How to add Enumeration Table under corresponding Attributes in Custom Documents in Sparx Enterprise Architect?


In Sparx Enterprise Architect I am trying to document a class model containing classes and attributes. Some attribute have a simple data type (e.g. Flag) and some have an enumeration type. All types (simple and enumeration) are modelled in separate classes. The model is stored in a single file with .qea extension ("repository as a file"), which is a SQLite database. Below the example of a class "Holiday" with several attributes. For example, Attribute "isDeferred" has a simple data type "FLAG". "holidayDurationType" has data type "DAYDURATIONTYPE" that is an enumeration. Both data types are described in a separate class as shown below.

Class "Holiday"
Enum of Attribute "HolidayDurationType" enter image description here

My goal is to generate a document that lists the following:

Class A
Attribute A1
Type A1 (simple data type or enum)
Attribute A2
Type A2 (simple data type or enum)
...

Here is a PDF example of the document I try to generate: enumeration table

(1) If the type is a simple data type, I only need the name (e.g. FLAG) of the data type class (see Attribute "isDeferred" above).

(2) If the type is an enumeration, I need the name, notes and enumerations (= attributes) of the data type class. The enumerations shall be displayed in a two column table. Column 1 shows the enumeration code (1,2...) and column 2 shows the notes (see Attribute "holidayDurationType" above).

To solve this I created a Custom Document Template that includes a Custom Template Fragment containing a Custom SQL query.

Custom Document Template "UserManual" Edit: Thanks to @Gert Bellekens' answer, the custom template code has been updated to provide the whole attribute section as a template fragment in the element > section.

package >
element >
   Class "{Element.Name}"
   {Element.Notes}
   {Template - Attribute_and_DataType}
< element
< package

Custom Template Fragment "Attribute_and_DataType"
Edit: Thanks to @Gert Bellekens' answer, the custom fragment code has been updated to include the whole attribute and data type information in a custom template fragment.

custom >
   Attribute "{AttName}"
             {AttDesc.Formatted}

             Domain: {AttType}
             {TypeDesc.Formatted}
             {Enums.Formatted}
< custom

SQL query in Template Fragment Options\Custom Query\Custom SQL Edit: Thanks to @Gert Bellekens' answer, the custom SQL code in the custom template fragment has been enriched to show all enumeration values and their description for each attribute that has an enumeration data type.

select 
  a.Name as 'AttName', 
  a.Notes as 'AttDesc.Formatted', 
  a.Type as 'AttType', 
  e.Note as 'TypeDesc.Formatted',
  (select group_concat(CAST(ev.[Default] + ':   ' + coalesce(ev.Notes, 
  '') as text), char(10)) 
      from t_object e 
      inner join t_attribute ev on ev.Object_ID = e.Object_ID
      where e.Object_ID = a.Classifier
      and e.Object_Type = 'Enumeration'
      ) as 'Enums.Formatted'
from 
  t_attribute a
inner join 
  t_object e on a.Classifier = e.Object_ID
where 
  a.Object_ID = #OBJECTID#

The result I receive when I drag and drop a Class (e.g. "Holiday") into a document and apply the Custom Template "UserManual", looks as follows.

enter image description here

Edit: Thanks to @Geert Bellekens the document generation works now and produces all the information needed. However, I do not manage to bring the enumerations (code and notes) into a table like in the PDF example above.

I tried the following:

  1. Added a table to the template fragment and moved Enums.Formatted in the table field.

Template fragment
enter image description here

The result looks as follows: enter image description here

There are two problems with this approach.
(1) an empty table is generated for all attributes with simple data type (e.g. FLAG).
(2) There is, of course, no separate column and row for each enumeration value/description as the SQL query produced just one text (group_concat, CAST(..., as text)) with line breaks (char10).

Is there a way to adjust the SQL query so that enumeration value and description go to separate columns and rows (e.g. markup tags in SQL query so that EA will render it as a 2 column table)? Any ideas are much appreciated.

  1. Adjusted the SQL query and template fragment:

SQL query

select
    a.Name as 'AttName', 
    a.Notes as 'AttDesc.Formatted', 
    a.Type as 'AttType', 
    e.Note as 'TypeDesc.Formatted', 
    ev.[Default] as 'EnumCode',
    ev.Notes as 'EnumDesc.Formatted'
from 
    t_attribute a
inner join 
    t_object e on a.Classifier = e.Object_ID
left join 
    t_attribute ev on ev.Object_ID = e.Object_ID
where 
    a.Object_ID = #OBJECTID#

Template fragment
enter image description here

The result looks as follows: enter image description here

There are two problems with this approach:
(1) empty table for attributes with simple data type.
(2) each enumeration value/description is in a separate table in a duplicate attribute section.

Any ideas how get it solved with this approach?

  1. Had a look at the Sparx EA Template Selector. I was wondering if I could create two template fragments, one for the simple data types (no table) and one for the enumeration data types (with table).
    The problem here to my understanding is that the template selector fragment takes the type and stereotype of the selected element to decide which template will be applied. As the type and stereotype of the element (Class) I drag and drop into the document is always "Class"/"EMLClassObj", there is no differntiation possible.

Any ideas how to solve it with a Template Selector?

Or am I completely on the wrong way and need to start with a different approach (like custom scripts)?


Solution

  • As suggeste by @Geert Bellekens I had a try with Document Script Fragment and managed to document enumeration data types in a table (each enum in separate row, code and description in separate columns).

    my solution approach:

    Create a custom template with a template fragment 'templateSelector' in the element > section.

    template_userManual

    The fragment 'templateSelector' contains just a custom > section

    fragment_templateSelector

    In the Document Options of the fragment, go to 'Custom Query' and select 'Document Script' as template fragment type and select via the dropdown the Custom Script ('getAttributeAndType') to get the attributes and their types (see further below). Call the script getAttributeAndType(#OBJECTID#) in the window and pass the #OBJECTID#

    custom_query_window

    Create a Custom Script. The Custom Script 'getAttributeAndType' gets the attribute name and notes and calls two other templates 'template_simpleType' and 'template_enumType' depending on whether the data type is simple (e.g. FLAG) or an enumeration.

    !INC Local Scripts.EAConstants-JScript
     
    var ENUM_TYPE_TEMPLATE = "template_enumType";
    var SIMPLE_TYPE_TEMPLATE = "template_simpleType";
     
    function getAttributeAndType(objectID)
    {
        var docGenerator as EA.DocumentGenerator;
            docGenerator = Repository.CreateDocumentGenerator();
            if ( docGenerator.NewDocument("") )
            {  
                try
                {
                    var currentElement as EA.Element;
                        currentElement = Repository.GetElementByID(objectID);
                
                    var attributesCollection as EA.Collection;
                        attributesCollection = currentElement.Attributes;
                    
                    for ( var i = 0; i < attributesCollection.Count; i++) {
                        
                        var currentAttribute as EA.Attribute;
                            currentAttribute = attributesCollection.GetAt(i);
                        
                        docGenerator.InsertText("Attribute: " + currentAttribute.Name,"");
                        docGenerator.InsertText("\n","");
                        docGenerator.InsertText(currentAttribute.Notes,"");
                        
                        var currentAttributeTypeElement as EA.Element;
                            currentAttributeTypeElement = Repository.GetElementByID(currentAttribute.ClassifierID);
                        
                        if(currentAttributeTypeElement.Type == "Enumeration")
                            docGenerator.DocumentElement(currentAttributeTypeElement.ElementID,1,ENUM_TYPE_TEMPLATE);
                        
                        else if(currentAttributeTypeElement.Type == "DataType")
                            docGenerator.DocumentElement(currentAttributeTypeElement.ElementID,1,SIMPLE_TYPE_TEMPLATE);
                        
                        else Session.Output("Data type not recognized");
                    }
                }
                catch(e)
                {
                    Session.Output(e);
                }
                var rtf = docGenerator.GetDocumentAsRTF();
                
                return rtf;
                
            }
         
        return "";
    } 
    

    The two templates being called by the script look as follows:

    template_enumType:

    template_enumType

    template_simpleType:

    template_simpleType

    All in all, you need a three templates, one fragment and one script. The first template calls the fragment, the fragment calls the script, the script calls the other two templates.