Author Topic: Implementing "Find in all Diagrams" in a script  (Read 944 times)

yonatan.lehman

  • EA User
  • **
  • Posts: 45
  • Karma: +0/-0
    • View Profile
Implementing "Find in all Diagrams" in a script
« on: May 27, 2022, 01:02:55 am »
Hi
I need to check in JavaScript (EA V14.0) if an element (e.g. Activity, Component) is used in any diagram.
i.e. the same as doing Find in all Diagrams (^U) in the project  browser
The best I can find at the moment is:

1) get all the model diagrams
diagramList = Repository.GetReferenceList("Diagram")
(I assume this is the same as walking down the entire project tree looking for diagrams - but much faster)

2) nested on all diagram objects, and on all DiagramObjects in each diagram

3) Check if the DiagramObjects refers to the required element
   Here is where I'm stuck.... How do I find the ID of the element being referred to by the diagram object?
   In the UI Diagram Properties, I can see that it in the Behavior Tab, Behavior Field, as a long string of type Package::SubPackage::ElementName
    a) How do I convert that string to the ElementID or how do I get the path to the ElementID to compare them?
    c) What is the Behavior Field and how do I access it ?- it is not mentioned anywhere in the API reference


Thanks
Yonatan







qwerty

  • EA Guru
  • *****
  • Posts: 12823
  • Karma: +366/-295
  • I'm no guru at all
    • View Profile
Re: Implementing "Find in all Diagrams" in a script
« Reply #1 on: May 27, 2022, 01:51:56 am »
Try a
Code: [Select]
SELECT COUNT * diagram_id FROM t_diagramobjects WHERE object_id = <sought obj-id> GROUP BY diagram_id
and pass that to
Code: [Select]
repository.SQLQuery(sql)
Pls. note that I wrote the above just from memory without verifying it in EA. If the count is > 0 you have it in so many different diagrams.

I guess that Geert will come up with something more sophisticated.

q.

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 11849
  • Karma: +460/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: Implementing "Find in all Diagrams" in a script
« Reply #2 on: May 27, 2022, 03:02:07 am »
You seem to be making things a lot more complicated than they have to be.

To know if an element is used on a diagram you an simply query the diagramObjects as q suggested
The "group by" is not necessary, and you'll have to give your count a name or EA will choke on it trying to make an xml from the query results.

This query will give you a list of diagramIDs of all diagrams that show your element as a link.
Code: [Select]
select do.Diagram_ID
from t_diagramobjects do
where do.Object_ID = <myObjectID>

Now you maybe also want to see if you element is use as an classifier.
In that you case you'll wan to make another join on t_object through the classifier field.
You'll need a distinct here because there can be multiple objects classified by your object on this diagram.

Code: [Select]
select distinct do.Diagram_ID
from t_diagramobjects do
inner join t_object o on o.Object_ID = do.Object_ID
inner join t_object oc on oc.Object_ID = o.Classifier
where oc.Object_ID = <myObjectID>


And of course if you want a single list of diagrams for both instances and links, you combine the two queries with a union

Code: [Select]
select do.Diagram_ID
from t_diagramobjects do
where do.Object_ID = <myObjectID>
select do.Diagram_ID
union
from t_diagramobjects do
inner join t_object o on o.Object_ID = do.Object_ID
inner join t_object oc on oc.Object_ID = o.Classifier
where oc.Object_ID = <myObjectID>

No more need for the distinct as the union will take care of the duplicate rows.

Then you pass that query to repository.SQLQuery, parse the XML, and get the diagrams by their ID.

Trying to traverse every single diagram, and loop every single diagramobject will easily take hours on serious model.
Doing it like this will take a few seconds max.

Geert

yonatan.lehman

  • EA User
  • **
  • Posts: 45
  • Karma: +0/-0
    • View Profile
Re: Implementing "Find in all Diagrams" in a script
« Reply #3 on: May 27, 2022, 04:21:20 am »
Thanks for you answers
Now after studiously ignoring SQL for 40 years (I'm an Embedded Sweng) I'm going to get my hands "dirty"  :o

I see that the EAScriptLib has a JScript-Database script - I assume I can build on that or at least get an idea of how to do things there - right ?

Any other resources you can suggest to quickly get something up and running ?

Paolo F Cantoni

  • EA Guru
  • *****
  • Posts: 8194
  • Karma: +232/-129
  • Inconsistently correct systems DON'T EXIST!
    • View Profile
Re: Implementing "Find in all Diagrams" in a script
« Reply #4 on: May 27, 2022, 08:20:02 am »
Thanks for you answers
Now after studiously ignoring SQL for 40 years (I'm an Embedded Sweng) I'm going to get my hands "dirty"  :o
[SNIP]
(my emphasis)
Look on the bright side, Yonatan!  You can now add "Experience with a Functional Language" to your CV ;D

Happy Friday, everybody!   ;)
Paolo
« Last Edit: May 27, 2022, 08:23:21 am by Paolo F Cantoni »
Inconsistently correct systems DON'T EXIST!
... Therefore, aim for consistency; in the expectation of achieving correctness....
-Semantica-
Helsinki Principle Rules!

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 11849
  • Karma: +460/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: Implementing "Find in all Diagrams" in a script
« Reply #5 on: May 27, 2022, 02:28:59 pm »
Any other resources you can suggest to quickly get something up and running ?

You can have a look at my VBScript library: https://github.com/GeertBellekens/Enterprise-Architect-VBScript-Library

Geert

yonatan.lehman

  • EA User
  • **
  • Posts: 45
  • Karma: +0/-0
    • View Profile
Re: Implementing "Find in all Diagrams" in a script
« Reply #6 on: June 02, 2022, 11:33:46 pm »
Thanks Geert
I tried your script above
and passed to Repository.SQLQuery the following string  (I separated it into lines to match what you wrote)

Code: [Select]
select do.Diagram_ID 
 from t_diagramobjects do 
 where do.Object_ID = 46665
 select do.Diagram_ID 
 union  from t_diagramobjects do
 inner join t_object o on o.Object_ID = do.Object_ID
 inner join t_object oc on oc.Object_ID = o.Classifier
 where oc.Object_ID = 46665;

Where the 46665 is theObject.ElementID

I got a dialog error that says:
DAI.Database [3075]
Syntax error in query expression 'do.Object_D = 46665 select do.Diagram_ID',


As far as I can see I copied what you wrote correctly just replacing <myObjectID> with theObject.ElementID

What did I do wrong ? Thanks
BTW - where are the EA SQL name (e.g Diagram_ID, t_diagramobjects, Object_ID) documented?

qwerty

  • EA Guru
  • *****
  • Posts: 12823
  • Karma: +366/-295
  • I'm no guru at all
    • View Profile
Re: Implementing "Find in all Diagrams" in a script
« Reply #7 on: June 03, 2022, 12:26:35 am »
That just looks like wrong SQL syntax. You better start with simple SQLs (and some tutorial) first...

q.

yonatan.lehman

  • EA User
  • **
  • Posts: 45
  • Karma: +0/-0
    • View Profile
Re: Implementing "Find in all Diagrams" in a script
« Reply #8 on: June 03, 2022, 12:42:02 am »
Yup - found it by playing around and with a bit of googling...

The below passed the syntax check

for SQL newbies like me
1) FROM with INNER needs ")" as shown below
2) the union comes between the two selects

   var sql = "";

    sql += " select do.Diagram_ID "
        + " from t_diagramobjects do "
        + " where do.Object_ID = " + theObject.ElementID
        + " union"
        + " select distinct do.Diagram_ID"
        + " from ((t_diagramobjects do"
        + " inner join t_object o on o.Object_ID = do.Object_ID)"
        + " inner join t_object oc on oc.Object_ID = o.Classifier)"
        + " where oc.Object_ID = " + theObject.ElementID + ";"
   

yonatan.lehman

  • EA User
  • **
  • Posts: 45
  • Karma: +0/-0
    • View Profile
Re: Implementing "Find in all Diagrams" in a script
« Reply #9 on: June 03, 2022, 01:08:10 am »
And here is a full JScript function

Probably could be done more elegantly if I learned how to parse XML directly - but I have to get back to my real work....

Code: [Select]
!INC Local Scripts.EAConstants-JScript
!INC EAScriptLib.JScript-XML

 function iutils_GetDiagramOccurences(anObject) {
var num_diagrams;
var theObject As EA.Element;
theObject = anObject;

// Construct and execute the query
var sql = "";

sql += " select do.Diagram_ID "
     + " from t_diagramobjects do "
     + " where do.Object_ID = " + theObject.ElementID
+ " union"
     + " select distinct do.Diagram_ID"
     + " from ((t_diagramobjects do"
     + " inner join t_object o on o.Object_ID = do.Object_ID)"
     + " inner join t_object oc on oc.Object_ID = o.Classifier)"
     + " where oc.Object_ID = " + theObject.ElementID + ";"

var queryResult = Repository.SQLQuery( sql );
var stringValue;
var diagramIds;
if ( queryResult.length > 0 )
{
var resultDOM = XMLParseXML( queryResult );
if ( resultDOM ) {
diagramIds = XMLGetNodeTextArray(resultDOM, "//EADATA//Dataset_0//Data//Row//Diagram_ID" )
}
}
var diagramIdsNum = [];
var index = 0;
for (var id in diagramIds) {
diagramIdsNum[index++] = new Number( diagramIds[id] );
}
return diagramIdsNum;
 }

yonatan.lehman

  • EA User
  • **
  • Posts: 45
  • Karma: +0/-0
    • View Profile
Re: Implementing "Find in all Diagrams" in a script
« Reply #10 on: June 06, 2022, 04:47:57 pm »
The script above works find for Activities - but it does not find methods in a component.
In other words, I want to find if a component method is used on an arrow (connector) of a sequence diagram.

From a bit of playing around, it looks like in a sequence with one component with one self arrow there is only one diagramobject - the lifeline (i.e. the component). Looking at the list of connectors of the component I can see the connector whose name is the method - but I'm looking for a reference that points to the actual method in the component (as opposed to just matching the name.


The SQL I'm using is
```
    sql += " select do.Diagram_ID "
        + " from t_diagramobjects do "
        + " where do.Object_ID = " + id
        + " union"
        + " select distinct do.Diagram_ID"
        + " from ((t_diagramobjects do"
        + " inner join t_object o on o.Object_ID = do.Object_ID)"
        + " inner join t_object oc on oc.Object_ID = o.Classifier)"
        + " where oc.Object_ID = " + id  + ";"
```
And I assign id as follows:
```
    if (theObject.ElementID) {
       id = theObject.ElementID;
    } else if (theObject.MethodID) {
       id = theObject.MethodID
    }
```
So the SQL works when I search based on ElementID and not when I search on MethodID - but methods don't have an ElementID...
Thanks
« Last Edit: June 06, 2022, 06:36:18 pm by yonatan.lehman »

qwerty

  • EA Guru
  • *****
  • Posts: 12823
  • Karma: +366/-295
  • I'm no guru at all
    • View Profile
Re: Implementing "Find in all Diagrams" in a script
« Reply #11 on: June 06, 2022, 06:42:01 pm »
Operations (the UML term; methods is what Mickeysoft people use regularly) have t_operation.object_id relating it to t_object.

q.

yonatan.lehman

  • EA User
  • **
  • Posts: 45
  • Karma: +0/-0
    • View Profile
Re: Implementing "Find in all Diagrams" in a script
« Reply #12 on: June 06, 2022, 08:04:14 pm »
As far as I can tell - at least when examining the model via JSCRIPT objects, the method call arrow (connector) is not a diagramobject - the diagramobjects are the components, and the arrows are Connectors of that component.

If I would be doing this by script I think I would need to find the components (the diagamobjects) and then check their Connectors and see if the Connector name matches a method name.

How would I do that in SQL?

BTW - I have no idea how the order of the arrows in a particular sequence diagram are modeled.



Geert Bellekens

  • EA Guru
  • *****
  • Posts: 11849
  • Karma: +460/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: Implementing "Find in all Diagrams" in a script
« Reply #13 on: June 06, 2022, 09:21:09 pm »
You have to look in t_connector. Sequence connectors are a bit different from other connectors in such that they also contain the diagramID of the sequence diagram.
If the message references an operation, it has the Operation guid in a tagged value with the name operation_guid

This is the method I use on my Operation wrapper class to get the sequence diagram messages

Code: [Select]
        public HashSet<UML.Interactions.BasicInteractions.Message> getCallingMessages()
        {
            //this one we will try to find with a cunning sql query directly
            //sometimes the guid of an operation is not the same as the guid mentioned in the tag
            //to be sure the try to get both.
            string sqlCallingMessages =
                @"select c.Connector_ID  from ((t_connector c
                inner join t_connectortag ct on ct.ElementID = c.Connector_ID)
                inner join t_operation o on ct.[VALUE] = o.ea_guid)
                where c.Connector_Type in ('Sequence','Collaboration')
                and ct.Property = 'operation_guid'
                and ct.[VALUE] = '" + this.wrappedOperation.MethodGUID + @"'
                Union
                select c.Connector_ID  from ((t_connector c
                inner join t_connectortag ct on ct.ElementID = c.Connector_ID)
                inner join t_operationTag ot on ct.[VALUE] = ot.[VALUE])
                where c.Connector_Type in ('Sequence','Collaboration')
                and ct.Property = 'operation_guid'
                and ot.ElementID = " + this.wrappedOperation.MethodID;
            // return this.model.getRelationsFromQuery(sqlQuery).Cast<UMLMessage>().ToList();
            HashSet<UML.Interactions.BasicInteractions.Message> returnedMessages = new HashSet<UML.Interactions.BasicInteractions.Message>();
            foreach (Message message in this.EAModel.getRelationsByQuery(sqlCallingMessages).Cast<Message>().ToList())
            {
                if (!returnedMessages.Contains(message))
                {
                    returnedMessages.Add(message);
                }
            }
            return returnedMessages;

        }

Geert

yonatan.lehman

  • EA User
  • **
  • Posts: 45
  • Karma: +0/-0
    • View Profile
Re: Implementing "Find in all Diagrams" in a script
« Reply #14 on: June 06, 2022, 10:13:09 pm »
Spot on - thanks !