Navigate from and to Composite Diagrams with EA Navigator

With EA Navigator version 2.4.12.0 you can now navigate from and to composite diagrams of an element.

Recently I’ve been working a lot with BPMN models. BPMN models make extensive use of the composite diagram mechanism in EA to drill-down on the processes and sub-processes.

In a classical UML model we usually place the composite diagram under the element, in which case finding the composite diagram, or finding the element(s) that have a diagram as composite diagram, is trivial. They are at the same location in the project browser.BPMN_Library_Model

In most BPMN models however there’s separation between model and library where the library contains the elements, and the model the diagrams. In such a setup it suddenly becomes much harder to find the composite diagram (find in all diagram, then double click the element) and almost impossible to find the element(s) that have a specific diagram as composite diagram.

 

In other words drilling down is relatively easy, but drilling up becomes nearly impossible.

Navigate_Composite_diagramThis problem is now solved by the EA Navigator.  From the Business Process I can now easily navigate to the composite diagram, but more importantly, I can navigate back up to any elements that have this diagram set as their composite diagram.

 

More Information

More information about the EA Navigator add-in for Enterprise Architect can be found here:

Hierarchical usage search in Enterprise Architect with SQL

How can I find out where an element or one of its specialized elements is used on a diagram in Enteprise Architect?

With this SQL search you can answer that question immediately and in a useful way.

Hierarchical usage search regults

Free download

[ecwid_product store_id=”6824265″ product_id=”48156490″]

 The model

Suppose we have modeled an inheritance hierarchy of animals as such

Animals Hierarchy

And our animals are being used as the classifier of Activity partitions in various Activity diagrams

Activity2

Activity1

And on the occasional Sequence diagram

Interaction1

Even with a simple example like this one it is not trivial to find all diagrams that use a rodent, or a bird.

The query

The query should return all diagrams that use an element either as link or as classifier. It should also include the diagrams for the sub-classes of the element we are looking for.

In theory a search like this should be carried out recursively, traversing the hierarchy until it reaches the bottom of the hierarchy. Unfortunately SQL and recursive are not the best friends, so we will have to limit the search to a pre-defined number of levels. In this case we go three levels down, so from the parent, to the the children, the grandchildren and the great-grandchildren.

Each of these levels is queried individually and each of the queries are added together with unions.

The first part of the query is to find diagrams that use the parent element as a link:

select d.ea_guid AS CLASSGUID, d.Diagram_Type as CLASSTYPE, d.Name as DiagramName,  po.Name as UsedElement, 'Link' as UsageType,
package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from ((((((t_object po
inner join t_diagramObjects do on do.Object_ID = po.Object_ID)
inner join t_diagram d on d.Diagram_ID = do.Diagram_ID)
inner join t_package package on package.Package_ID = d.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where po.Name = '<Search Term>'

Then we get the diagrams that use the parent element as a classifier

union
select d.ea_guid AS CLASSGUID, d.Diagram_Type as CLASSTYPE, d.Name as DiagramName,  po.Name as UsedElement,'Classifier' as UsageType,
package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((((((t_object po
inner join t_object poi on po.Object_ID = poi.Classifier)
inner join t_diagramObjects do on do.Object_ID = poi.Object_ID)
inner join t_diagram d on d.Diagram_ID = do.Diagram_ID)
inner join t_package package on package.Package_ID = d.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where po.Name = '<Search Term>'

Then descending a level we get the diagrams showing the children as link. Note that we include all possible variations of Generalization and Realization just to be sure we have everything. EA has been know to be not too consistent with these connector types in the past.

union
select d.ea_guid AS CLASSGUID, d.Diagram_Type as CLASSTYPE, d.Name as DiagramName,  c1.Name as UsedElement,'Link' as UsageType,
package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from ((((((((t_object po
inner join t_connector poc1 on poc1.End_Object_ID = po.Object_ID)
inner join t_object c1 on c1.Object_ID = poc1.Start_Object_ID)
inner join t_diagramObjects do on do.Object_ID = c1.Object_ID)
inner join t_diagram d on d.Diagram_ID = do.Diagram_ID)
inner join t_package package on package.Package_ID = d.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where po.Name = '<Search Term>'
and poc1.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')

And we do the same for the children being used a classifier.

union
select d.ea_guid AS CLASSGUID, d.Diagram_Type as CLASSTYPE, d.Name as DiagramName,  c1.Name as UsedElement,'Classifier' as UsageType,
package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((((((((t_object po
inner join t_connector poc1 on poc1.End_Object_ID = po.Object_ID)
inner join t_object c1 on c1.Object_ID = poc1.Start_Object_ID)
inner join t_object c1i on c1.Object_ID = c1i.Classifier)
inner join t_diagramObjects do on do.Object_ID = c1i.Object_ID)
inner join t_diagram d on d.Diagram_ID = do.Diagram_ID)
inner join t_package package on package.Package_ID = d.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where po.Name = '<Search Term>'
and poc1.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')

Descending another level to the grandchildren

union
select d.ea_guid AS CLASSGUID, d.Diagram_Type as CLASSTYPE, d.Name as DiagramName,  c2.Name as UsedElement,'Link' as UsageType,
 package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
 from ((((((((((t_object po
inner join t_connector poc1 on poc1.End_Object_ID = po.Object_ID)
inner join t_object c1 on c1.Object_ID = poc1.Start_Object_ID)
inner join t_connector poc2 on poc2.End_Object_ID = c1.Object_ID)
inner join t_object c2 on c2.Object_ID = poc2.Start_Object_ID)
inner join t_diagramObjects do on do.Object_ID = c2.Object_ID)
inner join t_diagram d on d.Diagram_ID = do.Diagram_ID)
inner join t_package package on package.Package_ID = d.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where po.Name = '<Search Term>'
and poc1.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
and poc2.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')

And the grandchildren as classifier

union
select d.ea_guid AS CLASSGUID, d.Diagram_Type as CLASSTYPE, d.Name as DiagramName,  c2.Name as UsedElement,'Classifier' as UsageType,
 package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
 from (((((((((((t_object po
inner join t_connector poc1 on poc1.End_Object_ID = po.Object_ID)
inner join t_object c1 on c1.Object_ID = poc1.Start_Object_ID)
inner join t_connector poc2 on poc2.End_Object_ID = c1.Object_ID)
inner join t_object c2 on c2.Object_ID = poc2.Start_Object_ID)
inner join t_object c2i on c2.Object_ID = c2i.Classifier)
inner join t_diagramObjects do on do.Object_ID = c2i.Object_ID)
inner join t_diagram d on d.Diagram_ID = do.Diagram_ID)
inner join t_package package on package.Package_ID = d.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where po.Name = '<Search Term>'
and poc1.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
and poc2.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')

Then to the last level, the great-grandchildren as link

union
select d.ea_guid AS CLASSGUID, d.Diagram_Type as CLASSTYPE, d.Name as DiagramName,  c3.Name as UsedElement,'Link' as UsageType,
package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from ((((((((((((t_object po
inner join t_connector poc1 on poc1.End_Object_ID = po.Object_ID)
inner join t_object c1 on c1.Object_ID = poc1.Start_Object_ID)
inner join t_connector poc2 on poc2.End_Object_ID = c1.Object_ID)
inner join t_object c2 on c2.Object_ID = poc2.Start_Object_ID)
inner join t_connector poc3 on poc3.End_Object_ID = c2.Object_ID)
inner join t_object c3 on c3.Object_ID = poc3.Start_Object_ID)
inner join t_diagramObjects do on do.Object_ID = c3.Object_ID)
inner join t_diagram d on d.Diagram_ID = do.Diagram_ID)
inner join t_package package on package.Package_ID = d.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where po.Name = '<Search Term>'
and poc1.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
and poc2.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
and poc3.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')

An the last one, the great-grandchildren as classifier

union
select d.ea_guid AS CLASSGUID, d.Diagram_Type as CLASSTYPE, d.Name as DiagramName,  c3.Name as UsedElement,'Classifier' as UsageType,
package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((((((((((((t_object po
inner join t_connector poc1 on poc1.End_Object_ID = po.Object_ID)
inner join t_object c1 on c1.Object_ID = poc1.Start_Object_ID)
inner join t_connector poc2 on poc2.End_Object_ID = c1.Object_ID)
inner join t_object c2 on c2.Object_ID = poc2.Start_Object_ID)
inner join t_connector poc3 on poc3.End_Object_ID = c2.Object_ID)
inner join t_object c3 on c3.Object_ID = poc3.Start_Object_ID)
inner join t_object c3i on c3.Object_ID = c3i.Classifier)
inner join t_diagramObjects do on do.Object_ID = c3i.Object_ID)
inner join t_diagram d on d.Diagram_ID = do.Diagram_ID)
inner join t_package package on package.Package_ID = d.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where po.Name = '<Search Term>'
and poc1.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
and poc2.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
and poc3.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')

The complete query then becomes

select d.ea_guid AS CLASSGUID, d.Diagram_Type as CLASSTYPE, d.Name as DiagramName,  po.Name as UsedElement, 'Link' as UsageType,
package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from ((((((t_object po
inner join t_diagramObjects do on do.Object_ID = po.Object_ID)
inner join t_diagram d on d.Diagram_ID = do.Diagram_ID)
inner join t_package package on package.Package_ID = d.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where po.Name = '<Search Term>'
union
select d.ea_guid AS CLASSGUID, d.Diagram_Type as CLASSTYPE, d.Name as DiagramName,  po.Name as UsedElement,'Classifier' as UsageType,
package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((((((t_object po
inner join t_object poi on po.Object_ID = poi.Classifier)
inner join t_diagramObjects do on do.Object_ID = poi.Object_ID)
inner join t_diagram d on d.Diagram_ID = do.Diagram_ID)
inner join t_package package on package.Package_ID = d.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where po.Name = '<Search Term>'
union
select d.ea_guid AS CLASSGUID, d.Diagram_Type as CLASSTYPE, d.Name as DiagramName,  c1.Name as UsedElement,'Link' as UsageType,
package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from ((((((((t_object po
inner join t_connector poc1 on poc1.End_Object_ID = po.Object_ID)
inner join t_object c1 on c1.Object_ID = poc1.Start_Object_ID)
inner join t_diagramObjects do on do.Object_ID = c1.Object_ID)
inner join t_diagram d on d.Diagram_ID = do.Diagram_ID)
inner join t_package package on package.Package_ID = d.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where po.Name = '<Search Term>'
and poc1.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
union
select d.ea_guid AS CLASSGUID, d.Diagram_Type as CLASSTYPE, d.Name as DiagramName,  c1.Name as UsedElement,'Classifier' as UsageType,
package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((((((((t_object po
inner join t_connector poc1 on poc1.End_Object_ID = po.Object_ID)
inner join t_object c1 on c1.Object_ID = poc1.Start_Object_ID)
inner join t_object c1i on c1.Object_ID = c1i.Classifier)
inner join t_diagramObjects do on do.Object_ID = c1i.Object_ID)
inner join t_diagram d on d.Diagram_ID = do.Diagram_ID)
inner join t_package package on package.Package_ID = d.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where po.Name = '<Search Term>'
and poc1.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
union
select d.ea_guid AS CLASSGUID, d.Diagram_Type as CLASSTYPE, d.Name as DiagramName,  c2.Name as UsedElement,'Link' as UsageType,
package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from ((((((((((t_object po
inner join t_connector poc1 on poc1.End_Object_ID = po.Object_ID)
inner join t_object c1 on c1.Object_ID = poc1.Start_Object_ID)
inner join t_connector poc2 on poc2.End_Object_ID = c1.Object_ID)
inner join t_object c2 on c2.Object_ID = poc2.Start_Object_ID)
inner join t_diagramObjects do on do.Object_ID = c2.Object_ID)
inner join t_diagram d on d.Diagram_ID = do.Diagram_ID)
inner join t_package package on package.Package_ID = d.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where po.Name = '<Search Term>'
and poc1.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
and poc2.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
union
select d.ea_guid AS CLASSGUID, d.Diagram_Type as CLASSTYPE, d.Name as DiagramName,  c2.Name as UsedElement,'Classifier' as UsageType,
package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((((((((((t_object po
inner join t_connector poc1 on poc1.End_Object_ID = po.Object_ID)
inner join t_object c1 on c1.Object_ID = poc1.Start_Object_ID)
inner join t_connector poc2 on poc2.End_Object_ID = c1.Object_ID)
inner join t_object c2 on c2.Object_ID = poc2.Start_Object_ID)
inner join t_object c2i on c2.Object_ID = c2i.Classifier)
inner join t_diagramObjects do on do.Object_ID = c2i.Object_ID)
inner join t_diagram d on d.Diagram_ID = do.Diagram_ID)
inner join t_package package on package.Package_ID = d.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where po.Name = '<Search Term>'
and poc1.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
and poc2.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
union
select d.ea_guid AS CLASSGUID, d.Diagram_Type as CLASSTYPE, d.Name as DiagramName,  c3.Name as UsedElement,'Link' as UsageType,
package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from ((((((((((((t_object po
inner join t_connector poc1 on poc1.End_Object_ID = po.Object_ID)
inner join t_object c1 on c1.Object_ID = poc1.Start_Object_ID)
inner join t_connector poc2 on poc2.End_Object_ID = c1.Object_ID)
inner join t_object c2 on c2.Object_ID = poc2.Start_Object_ID)
inner join t_connector poc3 on poc3.End_Object_ID = c2.Object_ID)
inner join t_object c3 on c3.Object_ID = poc3.Start_Object_ID)
inner join t_diagramObjects do on do.Object_ID = c3.Object_ID)
inner join t_diagram d on d.Diagram_ID = do.Diagram_ID)
inner join t_package package on package.Package_ID = d.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where po.Name = '<Search Term>'
and poc1.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
and poc2.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
and poc3.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
union
select d.ea_guid AS CLASSGUID, d.Diagram_Type as CLASSTYPE, d.Name as DiagramName,  c3.Name as UsedElement,'Classifier' as UsageType,
package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((((((((((((t_object po
inner join t_connector poc1 on poc1.End_Object_ID = po.Object_ID)
inner join t_object c1 on c1.Object_ID = poc1.Start_Object_ID)
inner join t_connector poc2 on poc2.End_Object_ID = c1.Object_ID)
inner join t_object c2 on c2.Object_ID = poc2.Start_Object_ID)
inner join t_connector poc3 on poc3.End_Object_ID = c2.Object_ID)
inner join t_object c3 on c3.Object_ID = poc3.Start_Object_ID)
inner join t_object c3i on c3.Object_ID = c3i.Classifier)
inner join t_diagramObjects do on do.Object_ID = c3i.Object_ID)
inner join t_diagram d on d.Diagram_ID = do.Diagram_ID)
inner join t_package package on package.Package_ID = d.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where po.Name = '<Search Term>'
and poc1.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
and poc2.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')
and poc3.Connector_Type in ('Generalization', 'Realization', 'Generalisation', 'Realisation')

The results

If you execute the search for Rodent you get something like following

Hierarchical usage search results_raw

By dragging the column UsedElement up to the grouping header you get an even better result

Hierarchical usage search regults

Although the icon for diagrams in search results is a bit weird, you can still use them as you would other search results. You can double-click a line to open the diagram, or you can right click and select it in the project browser.

More about SQL Searches

Instant impact analyses in Enterprise Architect with SQL searches

One of the major benefits of using a tool such as Enterprise Architect is that you create traceability. You store the relations between different model elements in your model.

The tricky part is to effectively use that traceability for your impact analyses. Following these instructions you can create SQL Searches in EA that instantly show the impact a certain element has on the rest of the model and present them in a clear and useful way.

Traceability_results_final

The meta model

In order to do impact analysis you have to know, and preferable document, your meta model. The meta model describes which elements from your model are to connected to each other, and it also describes which relation is used.

For the benefit of this example lets start with an imaginary meta model.

Traceability_metamodel

While this view of the meta model already helps a lot we still need to know exactly how these meta-concepts are realized in our Enterprise Architect model.

The model

Traceability_example model

So we end up with a model that looks a bit like this. You see that even for a miniature model like this it comes rather complicated very quickly. The questions that we need to answer when doing impact analysis questions such as

  • If I change requirement RQ-002, which other elements in my model are impacted?
  • I I change the CreateNewOrder function, where can I expect impact?

In general you’ll want to know

  • If I change X how does that impact the rest of my model.

Graphically that looks a bit like this:

Traceability_views

Enterprise Architect has an excellent view called traceabilty view

Traceability_view

This is great when working on the model, but it doesn’t really give you an overview, and it can’t be used for exporting or document generation.

The query

In order to get an overview of all impacted elements will make a custom SQL Search. See Harvesting the power of EA’s SQL searches for more information on how to make and use SQL searches.

We’ll want to create a search starting from each of the different levels. From their we work our way through the meta-models layer using a union for each level.

Lets start with the first one, from the Requirements to Use Case,  to Business Process, and to Application Service.

It’s best to work through this gradually. The first query will only return the requirement itself.

select req.ea_guid AS CLASSGUID, req.Object_Type AS CLASSTYPE,'1_Requirement' as TraceLevel, req.Name, req.Stereotype
, package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((( t_object req
inner join t_package package on package.Package_ID = req.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where req.name like '#WC#<Search Term>#WC#'
and req.Object_Type = 'Requirement'

Traceability_searchFromReq1

The we tackle the next level and we go from the Requirement to the Use Case. We add this query with a union to the previous query.

union
select uc.ea_guid AS CLASSGUID, uc.Object_Type AS CLASSTYPE,'3_Use Case' as TraceLevel, uc.Name, uc.Stereotype
, package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((((( t_object req
inner join t_connector requc on requc.End_Object_ID = req.Object_ID)
inner join t_object uc on requc.Start_Object_ID = uc.Object_ID)
inner join t_package package on package.Package_ID = uc.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where req.name like '#WC#<Search Term>#WC#'
and req.Object_Type = 'Requirement'
and uc.Object_Type = 'UseCase'

Notice that we make a join to t_connector and then back to t_object for the Use Case. Mind the direction of the connector between use case and requirement. Since it starts at the use case and goes to the requirement we need to join them using the appropriate End_Object_ID or Start_Object_ID.

Next part is the Business Process. Again we join t_connector and t_object to reach the business processes

union
select bp.ea_guid AS CLASSGUID, bp.Object_Type AS CLASSTYPE,'2_Business Process' as TraceLevel, bp.Name, bp.Stereotype
, package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((((((( t_object req
inner join t_connector requc on requc.End_Object_ID = req.Object_ID)
inner join t_object uc on requc.Start_Object_ID = uc.Object_ID)
inner join t_connector ucbp on ucbp.Start_Object_ID = uc.Object_ID)
inner join t_object bp on ucbp.End_Object_ID = bp.Object_ID)
inner join t_package package on package.Package_ID = bp.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where req.name like '#WC#<Search Term>#WC#'
and req.Object_Type = 'Requirement'
and uc.Object_Type = 'UseCase'
and bp.Object_Type = 'Activity' and bp.Stereotype = 'process'

From the business process we can reach the Business Information Items. Notice that we only return the information items that are the results of the business processes. Information items that serve as input to our business are not impacted when we change our business process.

union
select bi.ea_guid AS CLASSGUID, bi.Object_Type AS CLASSTYPE,'2_Business Information Items' as TraceLevel, bi.Name, bi.Stereotype
, package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((((((((( t_object req
inner join t_connector requc on requc.End_Object_ID = req.Object_ID)
inner join t_object uc on requc.Start_Object_ID = uc.Object_ID)
inner join t_connector ucbp on ucbp.Start_Object_ID = uc.Object_ID)
inner join t_object bp on ucbp.End_Object_ID = bp.Object_ID)
inner join t_connector bpbi on bpbi.Start_Object_ID = bp.Object_ID )
inner join t_object bi on bpbi.End_Object_ID = bi.Object_ID )
inner join t_package package on package.Package_ID = bi.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where req.name like '#WC#<Search Term>#WC#'
and req.Object_Type = 'Requirement'
and uc.Object_Type = 'UseCase'
and bp.Object_Type = 'Activity' and bp.Stereotype = 'process'
and bi.Object_Type = 'InformationItem'

The last level we want to add to our impact analysis query is the Application Function. These functions are again linked to the use cases. Notice that we both test the stereotype for NULL as for an empty string. That is just to be sure to get all the Application Functions. EA is know to be inconsistent in some areas, sometimes using NULL, sometimes an empty string or 0.

union
select af.ea_guid AS CLASSGUID, af.Object_Type AS CLASSTYPE,'4_Application Function' as TraceLevel, af.Name, af.Stereotype
, package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((((((( t_object req
inner join t_connector requc on requc.End_Object_ID = req.Object_ID)
inner join t_object uc on requc.Start_Object_ID = uc.Object_ID)
inner join t_connector ucaf on ucaf.End_Object_ID = uc.Object_ID)
inner join t_object af on ucaf.Start_Object_ID = af.Object_ID)
inner join t_package package on package.Package_ID = af.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where req.name like '#WC#<Search Term>#WC#'
and req.Object_Type = 'Requirement'
and uc.Object_Type = 'UseCase'
and af.Object_Type = 'Activity' and (af.Stereotype is null or af.Stereotype = '')

Now if you paste all the different parts of the query together you can start doing impact analysis and see the impact a single requirement has to the rest of the system.

If at first you run the query the results look a bit like this

Traceability_results_raw

But if you drag the “TraceLevel” up to the grouping part

Traceability_results_group

and then remove the column altogether from the results then you get a much nicer looking result

Traceability_results_final

Now you can create similar searches from the other elements in your meta-model, each time working your way up or down the model.

Below the complete SQL code for the search described here.

select req.ea_guid AS CLASSGUID, req.Object_Type AS CLASSTYPE,'1_Requirement' as TraceLevel, req.Name, req.Stereotype
, package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((( t_object req
inner join t_package package on package.Package_ID = req.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where req.name like '#WC#<Search Term>#WC#'
and req.Object_Type = 'Requirement'
union
select uc.ea_guid AS CLASSGUID, uc.Object_Type AS CLASSTYPE,'3_Use Case' as TraceLevel, uc.Name, uc.Stereotype
, package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((((( t_object req
inner join t_connector requc on requc.End_Object_ID = req.Object_ID)
inner join t_object uc on requc.Start_Object_ID = uc.Object_ID)
inner join t_package package on package.Package_ID = uc.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where req.name like '#WC#<Search Term>#WC#'
and req.Object_Type = 'Requirement'
and uc.Object_Type = 'UseCase'
union
select bp.ea_guid AS CLASSGUID, bp.Object_Type AS CLASSTYPE,'2_Business Process' as TraceLevel, bp.Name, bp.Stereotype
, package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((((((( t_object req
inner join t_connector requc on requc.End_Object_ID = req.Object_ID)
inner join t_object uc on requc.Start_Object_ID = uc.Object_ID)
inner join t_connector ucbp on ucbp.Start_Object_ID = uc.Object_ID)
inner join t_object bp on ucbp.End_Object_ID = bp.Object_ID)
inner join t_package package on package.Package_ID = bp.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where req.name like '#WC#<Search Term>#WC#'
and req.Object_Type = 'Requirement'
and uc.Object_Type = 'UseCase'
and bp.Object_Type = 'Activity' and bp.Stereotype = 'process'
union
select bi.ea_guid AS CLASSGUID, bi.Object_Type AS CLASSTYPE,'2_Business Information Items' as TraceLevel, bi.Name, bi.Stereotype
, package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((((((((( t_object req
inner join t_connector requc on requc.End_Object_ID = req.Object_ID)
inner join t_object uc on requc.Start_Object_ID = uc.Object_ID)
inner join t_connector ucbp on ucbp.Start_Object_ID = uc.Object_ID)
inner join t_object bp on ucbp.End_Object_ID = bp.Object_ID)
inner join t_connector bpbi on bpbi.Start_Object_ID = bp.Object_ID )
inner join t_object bi on bpbi.End_Object_ID = bi.Object_ID )
inner join t_package package on package.Package_ID = bi.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where req.name like '#WC#<Search Term>#WC#'
and req.Object_Type = 'Requirement'
and uc.Object_Type = 'UseCase'
and bp.Object_Type = 'Activity' and bp.Stereotype = 'process'
and bi.Object_Type = 'InformationItem'
union
select af.ea_guid AS CLASSGUID, af.Object_Type AS CLASSTYPE,'4_Application Function' as TraceLevel, af.Name, af.Stereotype
, package.name as PackageName ,package_p1.name as Package_level1,package_p2.name as Package_level2 ,package_p3.name as Package_level3
from (((((((( t_object req
inner join t_connector requc on requc.End_Object_ID = req.Object_ID)
inner join t_object uc on requc.Start_Object_ID = uc.Object_ID)
inner join t_connector ucaf on ucaf.End_Object_ID = uc.Object_ID)
inner join t_object af on ucaf.Start_Object_ID = af.Object_ID)
inner join t_package package on package.Package_ID = af.Package_ID)
left join t_package package_p1 on package_p1.package_id = package.parent_id)
left join t_package package_p2 on package_p2.package_id = package_p1.parent_id)
left join t_package package_p3 on package_p3.package_id = package_p2.parent_id)
where req.name like '#WC#<Search Term>#WC#'
and req.Object_Type = 'Requirement'
and uc.Object_Type = 'UseCase'
and af.Object_Type = 'Activity' and (af.Stereotype is null or af.Stereotype = '')

EA Navigator 2.4 released

The main new feature of the version 2.4 of the EA Navigator is the Quicksearch. The Quicksearch feature is undoubtedly the fastest way to find anything in a (large) EA model. It is the type of feature which makes you wonder how you could live without it all that time before.

Developing the Quicksearch function was far from easy. I wanted something that resembles what Google does when you start typing, and I started things with a standard Windows Forms ComboBox. But after a while tinkering I finally had to give up and I started my own user control from scratch, combining a TextBox and a ListBox.

Furthermore the EA Navigator now no longer a strictly read-only add-in. With the feature to add an element to a diagram it now is able to make changes to a model for the first time.

Ad last but not least a lot of painfully boring work went into adding all the icons. The EA Navigator now uses more then 90 different icons in its tree.

What’s new in EA Navigator 2.4

Here are the changes for version 2.4.

Quicksearch

The Quicksearch feature is the new textbox on the top right of the EA Navigator window.

Quicksearch

Start typing in the Quicksearch box and you will get a list of all things in the model who’s name start with whatever you have typed.

Quicksearch_dropped

Hovering an item in the dropdown list will show you it’s fully qualified name in the tooltip.

Selecting an item will select it in the EA Navigator tree.

The Quicksearch also comes with a whole bunch of new options

Quicksearch_options

You can choose which types of items to search for, and with the Actions you can choose what to do when an item from the Quicksearch is selected.

Link to Element Feature navigation.

EA has the possibility to define links between features of an element such as Attributes or Operations using the Connect to Element Feature feature, which is very useful in a lot of situations.

Visually EA shows which feature is linked using brackets next to the connected Attribute or Operation.

LinkToElementFeature

The is all nice and dandy, but the downside of the story is that you can only see which features are linked by looking at the diagram.

Now with the EA Navigator you can simply navigate from one feature to the other

NavigateLinkToElementFeature

Add to Diagram

The add to diagram button will add the selected element in the EA Navigator tree to the currently opened diagram.

AddToDiagram

The element will be added to the top left corner of the diagram.

Navigate to GUID

A new button has been added that allows you to navigate to a GUID of an item in EA.

NavigateToGUID

Each item, elements, attributes, operations, diagrams, etc… has a unique id in the form of a GUID (example: {C06EF618-D57C-4f63-BF64-F5A5265694AE}).

Pressing the Navigate to GUID button will allow you to go to that element using it’s GUID. If there’s already a GUID in your windows clipboard then the EA Navigator will use that one. If not the EA navigator will show a dialog where you can past (or type) the GUID.

For elements shown in the project browser you can easily copy the GUID to your clipboard using the context menu Copy Reference|Copy Node GUID to Clipboard

CopyGUIDClipBoard

New Icons

The EA Navigator now shows correct icons for all possible element types in EA allowing you to easily see the difference between Use cases, Classes, Activities, etc..

The icons had become even more more important because of the Quicksearch function. When searching for an element it is especially useful to immediately which type it is.

Icons

Over 70 new icons has been added bringing the total number of icons used by the EA Navigator to 92.

Downloads

More Information

More information about the EA Navigator add-in for Enterprise Architect can be found here:

UML Best Practice: There are no Activities on an Activity Diagram

Short

Don’t use Activities on an Activity Diagram

Purpose

Model useful and UML compliant Activity Diagrams

Detail

UML Activity Diagrams are often used to depict a certain flow of events. One of the reasons Activity Diagrams are so popular is because they are very similar to flow charts, something all of us know from long before UML even existed.

So lots of people start out enthusiastically to draw Activity Diagrams.

Lets say that we are modelling the checkout at a cash register of a store.

We start out with an InitialNode called Start and then we draw a ControlFlow to the Activity Scan Items. We then continue with the Activity Process Payment and end up in the FinalNode Finished.

Checkout_simple_hor

So far so good, but now we want to deal with customers who need an invoice. In order to be able to print an invoice we need to ask the customer for its details such as name, address, VAT-number etc… After getting the company details we can process the Payment, and when the payment is finished we print the invoice.

When using Activities there are two possible solutions to model this workflow.

Checkout_DuplicatePayment

The first solution is to split up the flow into a Company flow and an Individual flow, but as you can see this would force us to duplicate the Process Payment activity; which is not acceptable of course. Duplicate elements very quickly turn your model into a maintenance nightmare.

Another solution would be to come back to the single Process Payment activity after registering the Company details.

Checkout_DuplicateDecision

But then we would need to split up the flow again after the Process Payment. This time we are not duplicating an activity but a decision, which is almost as bad. Another drawback is that this makes our activity diagram less readable because we can’t easily distinguish the two flows.

No the only real solution is to use Actions on the diagram instead of Activities.

Checkout_Actions

Now all Activities have been replaced by Actions, and the Process Payment actions now both invoke the same Process Payment Activity.

To conclude:

  • Activity: used to contain an Activity Diagram
  • Action: used put on Activity Diagrams

More UML best practices

EA Navigator 2.3 released

The focus of version 2.3 of the EA Navigator is usability.

As a user myself I’m in a good position to evaluate the user-experience of the tool, and I felt the EA Navigator was coming short on that aspect. So I decided to do something about that.

One of the most important improvements, and also the most difficult one, is the switch to background processing.

With all the new features in the latest version I (and other users too) noticed that the EA Navigator was seriously slowing down EA itself. The problem was the fact that the EA Navigator needed some time to build the whole tree for the selected element, and EA was waiting for the add-in to finish before continuing.

On a small local .eap file that effect wasn’t really noticeable, but on large DBMS repositories it became a serious problem, so much even that some users even preferred to uninstall the EA Navigator because of it.

To solve this issue I started experimenting with multithreaded processing. The idea that, after a new element was selected, that the EA Navigator would start loading the element in a background thread. That allows us to return the control to EA almost immediately. The result is that the user doesn’t need to wait for the EA Navigator to finish before continuing to use EA.

What’s new in EA Navigator 2.3

Here are the changes for version 2.3.

Performance improved

The overall performance has been improved by doing the time consuming work of the EA Navigator in a background thread.
When several elements are being selected before the EA Navigator has finished loading them they will get queued. So now you might notice now and then that the EA Navigator is catching up after you finished clicking.

New Toolbar

The new toolbar allows fast access to functions such as Select in Project BrowserOpen Properties, or To FQN.
There’s also a button for the new Settings dialog, and the About dialog

New Settings

You can now configure certain options in the EA Navigator. The options are stored on a per user basis in a config file in the user profile.

The available options are:

  • Doubleclick action:
    Decide what the EA navigator should do when you double-click on a node.
  • Show Toolbar:
    Show or hide the toolbar.
  • Show Context Menus:
    Show or Hide the Navigate context menu when right clicking on an element.
  • Track Selected Element:
    Controls whether or not the EA Navigator load the selected element in the navigator window.

Open in Navigator

If you have disabled tracking of the selected element in the settings then you have a new context menu option load the element in the navigator window.

Select relevant element when opening diagram

When opening a diagram via the Navigator window the relevant element will be selected. So if you open a sequence diagram from under the Operation/Diagrams section the message calling that operation will be selected

Show stereotypes in names of elements

Elements now show their stereotypes in the navigator window.
Up to 20 characters of stereotype information will be show. Multiple stereotypes are separated by a comma, and if there’s more than can be displayed there will be two dots at the end to indicate that.

Downloads

More Information

More information about the EA Navigator add-in for Enterprise Architect can be found here:

EA Navigator 2.2 released

Since the release of version 2.1 the EA Navigator has been quite stable. Not much need for major improvements or bugfixes.

So version 2.2 has been about little changes and updates.

The most remarkable new feature is the new context menu with the ability to open the properties dialog of an element. Not remarkable because of the feature itself, but because of the loops and holes I had to jump through to get that part working. Opening the properties dialog is not really a supported API function of EA, so I had to resort to using an undocumented CustomCommand function to hack my way into it. Unfortunately I never got it working for messages.

What’s new in EA Navigator 2.2

Open Properties via new context menu

Each element in the navigator now has a context menu when you right-click on it.

Open Properties  opens the properties dialog of the element.

Select in Project Browser  selects the element in the project browser, just like a double-click would.

Fully Qualified name in the tooltip

Hovering above an element will show the fully qualified name of that element in the tooltip.

This helps to quickly see where that element is coming from (and if you need that one, or another one).

Communication Diagrams

Next to sequence diagrams you can also have messages on Communication Diagram (the old Collaboration Diagrams). Version 2.2 now also supports Communication Diagrams the same way it supports Sequence Diagrams.

This feature was requested by Chris on Github.

Datatypes and Enumerations

Datatypes and Enumerations are now also supported the same way as classes.

Downloads

More Information

More information about the EA Navigator add-in for Enterprise Architect can be found here:

UML Best Practice: 5 rules for better UML diagrams

Following these 5 rules will make your UML diagrams easier to understand, cleaner, and more consistent.

Although that has no effect on the actual model, it will improve the communication with the stakeholders.

Rule 1: Less is more

Large diagrams containing heaps of elements actually convey less information then small focussed diagrams.
When reading such a large diagram your audience will not know what to focus on, and since there’s too much on there to actually pay attention to all elements, they will quickly give up trying altogether.

Show up with a diagram like this at your stakeholder, and you will have already lost his/her attention even before you start talking.

The diagram above is a good indication of how much, or how little, you should put on a diagram. My rule of thumb is that you need to be able to print the diagram on a single A4 sheet while keeping things readable.

Rule 2: No Crossings

This is a fairly common and well known rule. Try to avoid any two lines in your diagram to cross each other.

Uncrossing lines in your diagram sure make it more readable and understandable, but there’s more to it then that.  If you are unable to uncross the lines on your diagram then that is a sign that

  • a) there’s too much on the diagram (see rule 1 Less is more)
    It might be that you are showing two different aspects of the model in one diagram. In that case it might be better to create two different diagrams, each focused on one aspect.
  • b) there is some kind of design flaw in your model
    For some reason well designed models don’t have the crossing lines problem. I have no idea why or what it is exactly, I just noticed that a lot of the times, when I’m unable to “uncross” all the lines in a diagram, I discover a design flaw that, when fixed results in a diagram without crossing lines.
The following diagram contains exactly the same information, but has just been ordered differently as to make sure there are no crossing lines.

Rule 3: Orthogonality

It seems like a small thing, but making the lines in a diagram go only horizontal or vertical, and having all only right angles makes a diagram look better instantly.

The diagram below is uses a direct style for its connectors. they all go directly from one element to the other with a straight line.

The mere fact that the lines have all kinds of angles makes the diagram look a lot messier, and less understandable.

Below here again the same diagram, but now with all connectors styles set to orthogonal.

Exceptions to this rule are (for me) note links and all relations with use cases. For some reason they look better with a direct style.

Rule 4: Parents Up

When drawing generalization or realization hierarchies on a diagram always make sure the parent elements are higher then the child elements so the arrows always point upwards.

This rule is pretty intuitive for most UML modelers. Only now and then I encounter diagrams that don’t follow this rule and have their hierarchies upside down.

Diagrams like this, where the generalization arrows point downwards are harder to read. For some reason it takes a greater mental effort to understand this then when the arrows all point upwards.

In case you have multiple elements all descending from the same parent, it is recommendable to show the hierarchy in a vertical tree style.

Rule 5: Tidy Up

I realize this sound like a nagging mom, but for crying out loud: Tidy Up!

If you want to convey the message that your analysis is a well thought trough construction that will solve your stakeholders problems then you better show up with a nice and clean diagram.

When tidying up think about

  • Aligning elements, either by one of their sides (e.g Top) or by their centers. The latter works best when aligning vertically
  • Make elements the same size where possible

After tidying up the diagram looks a loot better

Now remember, following these diagramming rules will not make you a better analyst, nor will it result in better UML models.

But it will allow you to make a better impression when trying explain the fruits of your hard labor to your stakeholders. You will need less time explaining diagrams, and you will be able to spend more time focusing on the actual content.

More UML best practices

EA Navigator is now an official Sparx Systems 3rd party add-in

I’m proud to announce that the EA Navigator has made the “official” Sparx Systems 3rd party add-in list.

Sparx Systems doesn’t just publish any add-in for Enterprise Architect. Each add-in on the list has been demonstrated to the the people of Sparx, and only if they approve it it will be added to the list.

So a couple of week ago I had an appointment to do a web conference with Sparx to do a little demo of my add-in.

Now they have approved it and the part about the EA Navigator has been published, and it even has its own url for direct navigation: http://www.sparxsystems.com/products/3rdparty.html#EAnavigator.

This is how it looks like:

Tutorial: How to change the color of inactive selected items in Windows 7

Since I upgraded to a Windows 7 machine I had a problem seeing which element was selected in my Enterprise Architect project browser.

Not when it was selected and active (dark-blue), but when I went on to work on something in a diagram.

The standard “inactive selection color” of Windows 7 is just too faint.

To illustrate that, look at the picture on the left and try to figure out which element is actually selected.

Well, if you look really carefully you’ll notice that the background of “Primitive1” is actually just the slightest bit darker then the rest of the background.

When I first noticed this I tried to fix it by changing my monitor settings, but no amount of brightness, contrast  or color balance changes made the selection more visible without messing up everything else.

So then I started googling and I soon found the solution:

  • Select Start|Control Panel|Change the Theme
  • Once there choose Window Color
  • And Advanced appearance settings…
  • Then choose 3D objects as item and click on the dropdown for Color 1:  and click on Other…
  • Here you move the triangle on the right just a few nudges down
  • Now OK and Apply and wait until Windows has applied the settings.
  • Now check the inactive selection color again in EA. If all is well it should now look like this:
  • To be sure that you don’t loose this setting you can save your theme in the personalization window.