Sparx Systems Forum
Enterprise Architect => Automation Interface, Add-Ins and Tools => Topic started by: ZuluTen on June 30, 2014, 07:29:03 pm
-
Another week… another request for help, please:
I’ve got my MDG working happily, now including dynamic toolboxes, but the users of the target model have expressed a need to apply what I’ll describe as a ‘Reviewer Comment’ anywhere around the model.
I’ve set up a ‘Reviewer Comment’ stereotype, complete with tagged values (initiator, date, status etc) and a defined colour scheme to differentiate it from the remainder of the real model.
I’ve also set up a ‘Relates To’ stereotypical association (one comment to one-to-many elements)
I’ve added a Search Function that can trawl the model for all Reviewer Comments and display these as a table together with the model elements to which they apply.
What I would like to do is add two enhancements to the MDG:
1) Whenever a Reviewer Comment is created I would like the Auto Name Counter to add a unique sequential reference number prefix e.g. RC01, RC02 etc to the name of the Comment. I can make this work in a target model, but can’t figure out how to define it as part of the MDG so that it is automatically applied.
2) Once a Reviewer Comment has been associated with an element on one diagram, I would like the same (i.e. linked) Reviewer Comment to be added to any other diagram in which the target element appears. This avoids the risk of duplication that another reviewer will innocently add a similar/same comment.
Any tips/suggestions on how to achieve these features would be greatly appreciated.
-
1) AFAIK you can't do that (I might be wrong, though)
2) You need to write an add-in that does this job for you. Your MDG must then come along with the right add-in installer.
q.
-
Thank you for that clarification.
I’ve started writing a script to seek all the elements with stereotype of Reviewer Comment, and am jumping between your ‘ScriptingEA’ and ‘InsideEA’ books, but appear to have fallen down a gap in the middle:
In MS Access using vba I would have started with an SQL query along the lines of
strSQL = SELECT * FROM t_object WHERE stereotype = "Reviewer_Comment”
and then run it in the program in the form
recordset = CurrentDB.execute(strSQL)
After that I’d have processed the recordset, one record at a time, looking for the Supplier_ID of the connection that relates the Reviewer_Comment to its target element, and then gone through the package/diagrams collections to find out where the target elements appear.
Using EA Scripting I can happily get the ‘for each element in package’ loops and searches to run, but they seem slow, hence the desire to accelerate matters initially by using a recordset from t_object.
Unfortunately I keep getting errors - it seems that EA does not support recordsets for I can't even declare them.
What am I doing wrong, indeed can this be done?
-
Can you please clarify what you want to change? Maybe you can issue a SQL UPDATE but that might be complicate in many cases. So it's better to run the Repository.SQLQuery (with only those columns you want to read - which is mostly Object_ID) and then start a loop over the XML result where you issue Repository.GetElementByID and perform whatever operation is needed.
q.
-
I don’t need to change the contents of a Recordset; merely to read it, using some innerjoins to enable me to follow connectors.
If I understand you correctly, the EA equivalent to an Access Recordset is simply an xml ‘object’ which contains the SELECTed fields all of the records which satisfy the ‘WHERE’ test.
When you say "Repository.SQLQuery", is that the same function as using xml =SQLQuery(strSQL) where strSQL is a string containing the query?
In Access there is a facility to move forwards and backwards through the recordset, and to determine when the end has been reached using the .EOF flag.
Presumably to do this using the xml it is necessary to parse it, or is there a way in which I can move through it line at a time?
It is difficult for me to visualise what the xml resulting from the query looks like inside. Is there a command I can use within my script which will save it to an external file?
-
SQLQuery actually returns some XML string. You can simply print the XML result and will see what it contains. There should be some XML class in VB to parse XML. Sorry I can't say anything about it as I use VB only very rarely, but Google is your friend. Those XML classes also have methods to navigate like in a collection (and much more).
q.
-
By-passing this whole issue, do the Team Review and/or Element Discussion facilities not give you the sequenced review comment function you want?
-
By-passing this whole issue, do the Team Review and/or Element Discussion facilities not give you the sequenced review comment function you want?
No, not really: the example that I gave above was analogous to, but somewhat displaced from the real requirement.
-
SQLQuery actually returns some XML string. You can simply print the XML result and will see what it contains. There should be some XML class in VB to parse XML. Sorry I can't say anything about it as I use VB only very rarely, but Google is your friend. Those XML classes also have methods to navigate like in a collection (and much more).
q.
Thanks, I've now accomplished this and got two arrays:
1) Containing the Diagram_ID of every diagram in which the 'Object of Interest' appears.
2) Containing the Diagram_ID of every diagram in which the Reviewer Comment associated with the 'Object of Interest' appears.
The Array 2 is smaller than array 1 because the Reviewer Comment is likely to have been added to one diagram only - I now wish to programmatically show it in all other diagrams: the list in Array 2.
As I know both the Object_ID and the Diagram_ID, is it permissible to simply add records to the t_diagramobjects table? Or will I break something?
Obviously there is a cosmetic risk associated with randomly placing the object, but the short term imperative is to get it displayed.
-
Rather than fiddling directly with the table you should create diagram object with the according EA.DiagramObject class. This will allow to add element to the Diagram.DiagramObjects collection.
q.
-
Rather than fiddling directly with the table you should create diagram object with the according EA.DiagramObject class. This will allow to add element to the Diagram.DiagramObjects collection.
q.
Thanks for that, but I'm still struggling, so I looked to Section 5.9 which defines the class, including variables:
Position: Bottom, Top, Left, Right etc which can, at this stage, be any default values.
Also the Diagram_ID and the Element_ID, both of which I have derived from parsing the xml generated by my SQL queries.
My problem arises when I now turn to Section 3.7.3 and I just can’t see how to use what I know in the context you’ve shown it.
Although in my case the diagram and the element both already exists, whereas you're creating new.
I think the vb code should look like:
Dim objDsplyNew as EA.DiagramObject
objDsplyNew.Left = 400 : objDsplyNew.Right = 440
objDsplyNew.Top = -100: objDsplyNew.Bottom = -150
objDsplyNew.ElementID = intSourceID ‘an integer value e.g. 1071 telling it what element to drop
objDsplyNew.DiagramID = intTargetID ‘an integer value e.g. 83 telling it on which diagram to drop it
objDsplyNew.Update() ‘making it happen
My instinct is that somewhere in there needs to be an ‘AddNew’ command but I can’t understand how it should be phrased when the element being added is new only to this diagram, though I suppose it is a new line in the DiagramObjects collection ...
Thank you again.
-
You need to
objDsplyNew = diagram.DiagramObjects.AddNew("", "")
or
objDsplyNew = diagram.DiagramObjects.AddNew("l=400;r=440;t=-100;b=-150;", "")
That will create the object in the according diagram. You can omit the assignment of the diagramId (since that's implicitly done). For the latter you can also omit the coordinate specs.
q.
-
That will create the object in the according diagram. You can omit the assignment of the diagramId (since that's implicitly done). For the latter you can also omit the coordinate specs.
q.
Thank you yet again.
Sorry to sound argumentative, and thick, but how and why is the diagram assigned implicitly?
I have only the script running and there are no diagrams open.
The intended destination diagram is known only by its ID held inside an array in the script.
I've obviously missed something...
-
No problem. You need to have the diagram in question open at some point. Of course it depends how, but one way would be to use Repository.GetDiagramByID. Once you have the right Diagram object you can add new DiagramObjects to the associated collection Diagram.DiagramObjects. When you create a new element therein using the AddNew those will be assigned with the diagramId.
q.
-
Aha! The final missing piece: that works perfectly. Thank you so much.
Is there any point in me pasting the finished few lines of code for adding the objects, or are other viewers likely to be much more accomplished in VB/EA and not in need of such remedial help?
-
It definitely won't hurt :-) Me is not the power VB user (anymore) but others certainly are.
q.
-
In case this can be of use to anyone, this is what I did.
The input is a pair of arrays:
1) Containing the Diagram_ID of every diagram in which the 'Object of Interest' appears. i.e. in which the Reviewer Comment should appear.
2) Containing the Diagram_ID of every diagram in which the Reviewer Comment associated with the 'Object of Interest' currently appears.
Obviously the Reviewer Comment should only appear once in any diagram, hence the tests which appear surrounding the insert command.
MatchFound = False 'a status indicator that will be asserted when a match is found
For abacus = 1 to UBound(aryTargetAppearsInID) 'the array holding the list of diagramIDs in which the Flag should appear
For abacus2 = 1 to UBound(aryFlagAppearsInID) ' 'the array holding the list of diagramIDs in which the Flag currently appears
If aryTargetAppearsInID(abacus) = aryFlagAppearsInID(abacus2) Then 'the Flag already appears in that diagram
MatchFound = true 'assert the status indicator
end if
Next 'consider the next diagram in the list
If MatchFound = False Then 'it wasn't found anywhere, so add the Flag to the Diagram
'For debugging purposes:
Session.Output("Add It: ElementID " & intSourceID & " should be added to diagram with ID of " & aryTargetAppearsInID(abacus))
'Define a default position where the Flag will be added:
strAttrib = "Left = 300; Right = 400; Top = -400; Bottom = -470;"
Dim objNewElementinDiagram as EA.DiagramObject 'declare the new object
Dim objTargetDiagram as EA.Diagram 'declare the Diagram
tempLong = (CLng(aryTargetAppearsInID(abacus))) 'retrieve the destination Diagram's ID from the array and ensure it's Long
set objTargetDiagram = Repository.GetDiagramByID(tempLong) 'open that Diagram
set objNewElementinDiagram = objTargetDiagram.DiagramObjects.AddNew(strAttrib,"") 'Add the extra object
objNewElementinDiagram.ElementID = CLng(intSourceID) 'Define the source ID of the object - also Long
objNewElementinDiagram.Update() 'Update the Diagram
End If
Next