Searching for REAL orphans in Enterprise Architect
Enterprise Architect comes standard with an Find Orphans search, which is supposed to give you a list of all elements that are no longer used in the model, and thus better be removed from the model altogether.
The problem with this search is that it will only report elements that are not shown on a diagram; which should not be the only criterion to determine if an element is an orphan or not. Not being on a diagram is just fine. I have lots of elements in my model that are not on a diagram, that doesn’t mean they are not used anymore.
If you are going to delete all elements reported in the standard orphans search you might do serious damage to your model.
So in order to aid with the maintenance of a large model I wrote the following SQL Search.
select distinct o.ea_guid as CLASSGUID,o.Object_Type as CLASSTYPE,o.Name as Name, o.Stereotype, package.name as PackageName ,package_p1.name as PackageLevel1,package_p2.name as PackageLevel2 ,package_p3.name as PackageLevel3 from ((((((((((((((((( t_object o left join t_diagramobjects dob on dob.[Object_ID] = o.[Object_ID]) left join t_object inst on inst.[Classifier] = o.[Object_ID]) left join t_objectproperties otv on otv.VALUE = o.[ea_guid]) left join t_connectortag ctv on ctv.VALUE = o.[ea_guid]) left join t_attributetag atv on atv.VALUE = o.[ea_guid]) left join t_operationtag optv on optv.VALUE = o.[ea_guid]) left join t_object u on u.Pdata1 = o.ea_guid) left join t_connector cs on cs.Start_Object_ID = o.Object_ID) left join t_connector ce on ce.End_Object_ID = o.Object_ID) left join t_attribute att on att.Classifier like o.Object_ID) left join t_operation op on op.Classifier like o.Object_ID) left join t_operationparams opp on opp.Classifier like o.Object_ID) left join t_object owned on owned.ParentID = o.Object_ID) inner join t_package package on o.package_id = package.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 o.Package_ID in (#Branch#) and (o.name is null or o.Name like '#WC#<Search Term>#WC#') and o.Object_Type not in ('Package') and (o.Stereotype is null or o.Stereotype not in ('model document')) and dob.Object_ID is null and inst.Object_ID is null and otv.VALUE is null and ctv.Value is null and atv.Value is null and optv.Value is null and u.Object_ID is null and cs.Start_Object_ID is null and ce.End_Object_ID is null and att.Classifier is null and op.Classifier is null and opp.Classifier is null and owned.Object_ID is null
This search will look for all elements that
- Are located in the currently selected package branch
- Are not a package or a model document (section in a virtual document)
- Are not used on a diagram
- Are not used as the Classifier of an instance
- Are not referenced by any tagged value
- Are not used as the source or target of any relation
- Are not used as the type of an attribute
- Are not used as the return type of an operation
- Are not used as the type of a parameter
- Do not own any other elements
Elements that show up in this search are most probably real orphans that clutter your model and can be safely deleted.
Of course, before you delete anything from the model, make sure you have a backup!
In order to use this search create a new search of type SQL and paste the above query into the query builder field.
If you find anything that should be added to this search please let me know.
Geert, this is quite useful. However, when I use it on some of our models, it returns some activities that are parent to a (non-empty) diagram.(but the elements on the diagram are not under that activity).
Yes I can see that. You could add “does not own a non-empty diagram” as a criterion as well by joining t_diagram and t_diagramObject