Sparx Systems Forum

Enterprise Architect => Automation Interface, Add-Ins and Tools => Topic started by: David Rains (bioform) on January 11, 2011, 02:02:27 pm

Title: Scripting - Locate Assoc. Class' source class
Post by: David Rains (bioform) on January 11, 2011, 02:02:27 pm
I am working on a set of shape scripts to support SBVs (structured business vocabularies). I am trying to, via scripts, to locate the source class for an associated class (e.g., have Class1 and Class2, drag association class connector between the two and Class3 is created).

The issue I am having is how to locate the object ID of the source class( Class1) from the Class3 element in a script? If I remember right an associated classes' ID is stored in the connector's PDATA1 field...

Previously I did this by SQL calls to a hosted EA model (find the instance of the stereotyped Class3 object ID in the connector table under PDATA1, then use the StartObjectID and EndObjectIDs to find their tagged values I am interested in....

SBV Example: Class1 (term) is named "Dog", Class2 (term) is named "Hand", created associated class using connector and it will be named "DOG bites Hand" (a fact type), the verb "bites" would be displayed as the name label of the association, etc.

thanks for the help in advance... (aka Bioform)
David
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: Geert Bellekens on January 11, 2011, 05:24:12 pm
David,

Do you use an assocationClass or just a regular association?

For a regular association you should look into Connector.ClientID and Connector.SupplierID.

I wouldn't know how to figure this out for AssociationClasses, but what I would do is to create an empty model with only Client, Target and Association class.
Then open the database and look how these three things are connected.
If something is stored in the PDATA fields you can get them in a script with Element.MiscData

Geert
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: David Rains (bioform) on January 11, 2011, 06:34:35 pm
Yes, it is an association class that I stereotyped as a "Wording". The other is relatively simple. But EA creates a connector entry for the A-B association, and then stores the Object ID of C (the assocated class - in this case my stereotyped FactType class) in the connector's PDATA1 as a string value.

Since I am rather new to the use of scripting in EA (today is my first day in fact) I am unsure of HOW to:

Identify the connector ID when all I know is the object ID of the associated class (C)... I was assuming I could look at a collection of connectors, then examine the PDATA field for the Object ID value of C.

I noticed from reading earlier posts that the connectors are not treated like a regualr collection? I tried to just run through a collection of connectors, but kept getting a message about method not being available... even though auto-sense shows it....

I will post a snippet of my script to show where I am having the problem and error message.

BTW it sure is fun to be back working with EA... :) Still on version 7.5 but am planning on updating in the next week or so.... waiting for new job to start... :)

Regards,

david
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: Geert Bellekens on January 11, 2011, 07:18:24 pm
I would assume as well that you would need C.Connectors to gain access to the association.
Do post a snippet, I'm curious to what exactly is going wrong.

I can relate to your feelings. I had to work with MEGA for a year, and I sure was glad to be allowed to work with EA again.

Geert

PS. Version 9 is just around the corner, and it promises a whole bunch of improvements. Should be a matter of a few months before it is released.
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: David Rains (bioform) on January 13, 2011, 03:19:47 pm
Thanks for your help BTW :)

Okay, I decided to take a different more direct tack...
- Manually select the association-class connector in the diagram
- load the connector data
==============
dim theDiagram as EA.Diagram
set theDiagram = Repository.GetCurrentDiagram

dim theConnector as EA.Connector
set theConnector = theDiagram.SelectedConnector
==============
Everything working at this point... can see values for SupplierID and ClientID .... saved them to variables supplerID and clientID

Next load the supplier element's data
=========================
dim theSourceElement as EA.Element
set theSourceElement = Repository.GetElementByID(supplierID)
msgbox "Source: " & theSourceElement.ElementID, vbOkayOnly
=========================

Nothing? I re-read the snippet about GetElementByID and this seems to refer NOT to the EA assigned object ID, but to a local value of a collection?

Is there NOT a simple way to reference a element directly if you know it's EA objectID?

I seem to be finding myself in need of some basic code snippets to understand locating objects (elements, connectors, packages, etc.). I have checked the local scripts but they mostly depend on the element being already selected on the project tree (Repository.GetTreeSelected... )

BTW when are you starting that book Geert? :)
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: Geert Bellekens on January 13, 2011, 06:16:13 pm
No, AFAIK Repository.GetElementByID works as you think it does.
I've used that quite a lot in my addins, and I never had any problems with it.
What you could do is check if the supplierID you provide is in fact an Object_ID in the table t_object.

If I find the time I'll have a go at it on my system. Just curious, which version of EA are you using?

Geert

PS. about the book.. I don't know, the problem is that something like that would demand a huge investment (time-wise) and at the moment I can't afford to do much unpaid (or later-paid) work.
If I were to find a sponsor on the other hand ;D
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: Geert Bellekens on January 13, 2011, 06:42:09 pm
I just tested this on my machine (v 8.0.862) with following C# code:

      
Code: [Select]
public static void test()
        {
            ACVModel model = new UMLToolConnector().getCurrentModel();
            EA.Repository repo = ((EAModel)model.getUMLModel()).getWrappedModel();
            EA.Connector connector = repo.GetConnectorByID(1);
            EA.Element supplier = repo.GetElementByID(connector.SupplierID);
            EA.Element client = repo.GetElementByID(connector.ClientID);
            EA.Element associationClass = repo.GetElementByID(int.Parse(connector.MiscData[0]));
            string associationClassName = associationClass.Name;
        }
and it works perfectly. I have both the supplier, client and associationClass elements.

Geert
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: David Rains (bioform) on January 13, 2011, 06:43:35 pm
Well, I have done the rewrite and I am still getting the original error mesage when I try to GetElementByID.... Here is the code snippet
=================
45 - dim supplierID
46 - supplierID = theConnector.SupplierID
47 -                    
48 - dim supplierElement as EA.Element
49 - supplierElement = Repository.GetElementByID(supplierID)
=================

The error message is.... Object doesnt support this property or method. Line49.

I check the value with a msgbox and it displays "supplierID: 80" which is correct when I check the t_object table
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: Geert Bellekens on January 13, 2011, 06:45:44 pm
try "dim supplierID as Integer"
It might be that by passing a variant to the getElementByID you get the error.

Geert
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: David Rains (bioform) on January 13, 2011, 07:02:09 pm
I have been trying this using VBScript which supports only a variant type. I tried to force the issue by making this change
=================
supplierElement = Repository.GetElementByID(int(supplierID))
=================
But I still get the same error....

Now you might ask why don't I use VS2008 pro that I have installed on my laptop... good question. I tried to run the conversion for the VS2003 C# add-in example and the conversion was unsuccessful.

What I would LOVE to see posted is a add-in framework template in VB or C# for 2008... Hint Hint EA Admins :) - I can hack some pretty complex code using VBA but getting my 2008 environement set up to run the examples using outdated info been very fustrating on my end...

<whine whine whine...> :)

David
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: David Rains (bioform) on January 13, 2011, 07:07:39 pm
Just tried using Clng to force the subtype to long... but still getting that same error?!

thank god I'm going bald, because I don't have to go the hair pulling route to vent :)

David "Quicker in the Shower" Rains
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: Geert Bellekens on January 13, 2011, 07:18:01 pm
David,

Take a look at my EA navigator addin (http://community.sparxsystems.com/resources/scripts/navigator-addin-navigate-operations-sequence-diagrams-and-vice-versa) on the community site.
That includes the source code in C# and it should give you a good start for writing C# addins.

Geert
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: David Rains (bioform) on January 13, 2011, 07:29:22 pm
May your hair continue to grow and your feet never hurt!  :)
Now to go hide, read, and learn!  :)

Thanks again, and yes it is 3:30 AM and I should be in bed over here!

David
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: Geert Bellekens on January 13, 2011, 07:37:46 pm
Have fun.

To give you some more stuff to read: this page (http://themodelfactory.org/Pattern:Modelling_Tooling_Framework) describes the pattern I used to design the framework for my addin.

Geert
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: David Rains (bioform) on January 13, 2011, 07:40:54 pm
Perfect timing! I had the source open and was browsing the TMF wiki!!
WOW that is some resource!

Just make sure you and Palo never pass on to the next what ever okay? ;)
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: David Rains (bioform) on January 13, 2011, 08:05:43 pm
For completness here is the full code for the VBScript
=======================================
option explicit

'Process the newly created wording connector

'Assumptions:
'      - a valid sbvrWording connector (conWording) is selected in the current diagram
'            - the connector stores the associated class ID in PDATA1 (access via .MiscData(#-1)
'            - the connector has the necessary tag values (e.g., verb_phrase_forward/reverse)
'            - the connector associations a new class with 1 or 2 <sbvrTerm> classes (unary or binary)
'            - the newassociation class has NOT been stereotyped yet
'      - the associated term(s) have been previously named
'      - user will supply a forward and reverse verb phrase when prompted

'Example Data:
'      - Term Names = A, B
'      - verb phrase forward = precedes, reverse = follows

'Success Outcome:
'      - associated clase name will be derived and assigned (e.g., A precedes B)
'      - associated class will be assigned the correct stereotype (e.g., sbvrFactType)
'      - wording connector will display 'precedes' in the .... label
'

'TO DO LIST
'      - add error checking

sub sbvrProcessWordingConnector()
      
      ' Get the currently selected connector in the diagram to work on
      dim theDiagram as EA.Diagram
      set theDiagram = Repository.GetCurrentDiagram

      dim theConnector as EA.Connector
      set theConnector = theDiagram.SelectedConnector
      
      on error resume next
      if theConnector is nothing or theConnector.Stereotype <> "sbvrWording" or theConnector.MiscData(0) = "" then 'PDATA# is (#-1)
            ' No item selected in thediagram, or the item selected was not expected
            MsgBox( "This script requires a sbvrWording connector be selected in the current diagram." & chr(10) & _
                  "Please try again." )
            on error goto 0            'Turn Error checking back on
      else
            on error goto 0            'Turn Error checking back on
            'Msgbox( "Success")
                  
            dim supplierElement as EA.Element
                  supplierElement = Repository.GetElementByID(theConnector.SupplierID)   'ERROR OCCURS HERE!!            
            dim clientElement as EA.Element
                  clientElement =Repository.GetElementByID(theConnector.ClientID)

            msgbox("Supplier and Client IDs: " & supplierID & " <" & supplierElement.Name & ">, " & clientID & " <" & clientElement.Name & ">")
      end if

      set theConnector = nothing
      set theDiagram = nothing

end sub

sbvrProcessWordingConnector
=======================================
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: David Rains (bioform) on January 14, 2011, 10:20:17 am
Okay I just could not let go of this and just scrapped the whoile thing and started from scratch... oif course things worked fine now?!!

anyway here is the working solution.... and this thread can be closed!
====================
option explicit

sub main()

      dim currentDiagram as EA.Diagram
      set currentDiagram = Repository.GetCurrentDiagram
      
      dim currentConnector as EA.Connector
      set currentConnector = currentDiagram.SelectedConnector
      
      on error resume next
      if currentConnector is nothing or currentConnector.Stereotype <> "sbvrWording" or currentConnector.MiscData(0) = "" then 'PDATA# is (#-1)
            ' No item selected in thediagram, or the item selected was not expected
            MsgBox( "This script requires a sbvrWording connector be selected in the current diagram." & chr(10) & _
                  "Please try again." )
            on error goto 0            'Turn Error checking back on
      else
            on error goto 0            'Turn Error checking back on
            msgbox "Connector Name, ID, and GUID: " & currentConnector.Name & ", " & currentConnector.ConnectorID & ", " & currentConnector.ConnectorGUID ,vbOKOnly

            dim sourceElement as EA.Element
            set sourceElement = Repository.GetElementByID(currentConnector.SupplierID)
            'set elementSelected = Repository.GetTreeSelectedObject
                  msgbox "Source Element Name, ID, and GUID: " & sourceElement.Name & ", " & sourceElement.ElementID & ", " & sourceElement.ElementGUID ,vbOKOnly
            dim clientElement as EA.Element
            set clientElement = Repository.GetElementByID(currentConnector.ClientID)
            'set elementSelected = Repository.GetTreeSelectedObject
                  msgbox "Client Element Name, ID, and GUID: " & clientElement.Name & ", " & clientElement.ElementID & ", " & clientElement.ElementGUID ,vbOKOnly

            dim assocc_classElement as EA.Element
            set assocc_classElement = Repository.GetElementByID(currentConnector.MiscData(0))
            'set elementSelected = Repository.GetTreeSelectedObject
                  msgbox "Assoc. Class Element Name, ID, and GUID: " & assocc_classElement.Name & ", " & assocc_classElement.ElementID & ", " & assocc_classElement.ElementGUID ,vbOKOnly

            set sourceElement = nothing
            set clientElement = nothing
            set assocc_classElement = nothing

      end if

      set currentConnector = nothing
      set currentDiagram = nothing
end sub
main
====================
Title: Re: Scripting - Locate Assoc. Class' source class
Post by: mrf on January 14, 2011, 11:32:22 am
Glad to hear you got everthing working. There will be improved support for Association Classes through the automation interface in version 9.

Quote
I re-read the snippet about GetElementByID and this seems to refer NOT to the EA assigned object ID, but to a local value of a collection?

I'm not sure if I'm reading into this wrong (having not seen the source of your quote), but I don't think that statement is accurate.

An object ID is unique within the context of a repository, but not globally - which is why objects both have IDs (repository unique identifier) and GUIDs (globally unique identifier).

If you import/export between repositories you will notice that the IDs change but the GUIDs do not. As a result, I would not expect GetElementByID to fail if the element ID you are using comes from the current repository.