Book a Demo

Author Topic: Scripting : copy diagram between packages  (Read 18004 times)

Danny F

  • EA User
  • **
  • Posts: 60
  • Karma: +0/-0
    • View Profile
Scripting : copy diagram between packages
« on: October 03, 2012, 05:19:12 pm »
(using EA 9.2)

I'm trying to (shallow) copy a diagram from one package to another via a JScript
The original diagram should stay in the original package (no 'cut')

Is that possible ?

Thanks
« Last Edit: October 03, 2012, 05:22:16 pm by dannyf »
Reg.

Danny

Ian Mitchell

  • EA User
  • **
  • Posts: 507
  • Karma: +22/-4
  • The eaDocX and Model Expert guy
    • View Profile
Re: Scripting : copy diagram between packages
« Reply #1 on: October 03, 2012, 07:40:50 pm »
Sounds like you're struggling with the RTF generator.
Have you looked at eaDocX ?
Ian Mitchell, Designer, eaDocX


www.eaDocX.com
www.theartfulmodeller.com

Danny F

  • EA User
  • **
  • Posts: 60
  • Karma: +0/-0
    • View Profile
Re: Scripting : copy diagram between packages
« Reply #2 on: October 03, 2012, 08:07:19 pm »
Well, I'm (struggling with RTF generator)  ::)

I had a quick look at eaDocx - but not sure it will solve my problem ?
I had the impression that the 'specific package structures' have to be manipulated manually, before launching the document generation ?

I want the 'specific package structure' to be generated by a script.
(and then change model document attributes accordingly, see other post)

Maybe I need to take a closer look to eaDocX ?
Reg.

Danny

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: Scripting : copy diagram between packages
« Reply #3 on: October 08, 2012, 06:31:34 pm »
Danny,

I don't think the native copy operations are exposed in the API, but it should be relatively simple to duplicate a diagram.

Do do so you should:

- Create a new diagram in your new package and copy all attributes from the original diagram to the new diagram
- Create a copy of each DiagramObject of the original diagram in the new diagram
- Create a copy of each DiagramLink of the original diagram in the new diagram.

And that should be it.

Geert

pakcom

  • EA Novice
  • *
  • Posts: 13
  • Karma: +0/-0
    • View Profile
Re: Scripting : copy diagram between packages
« Reply #4 on: October 09, 2012, 02:42:04 am »
@Geert
How do you create a copy of diagram link?

I have done copy diagram object this way:
Code: [Select]
// copy diagram objects
foreach (EA.DiagramObject ref_dia_obj in refDiagram.DiagramObjects)
{
    EA.DiagramObject new_dia_obj = diagram.DiagramObjects.AddNew("l=" + ref_dia_obj.left +";r=" + ref_dia_obj.right +";t=" + ref_dia_obj.top +";b=" + ref_dia_obj.bottom + ";", "");
    new_dia_obj.ElementID = ref_dia_obj.ElementID;
    new_dia_obj.Update();
}

But, I don't know how to copy diagram links  :(
Can you show me how to copy the diagram links?
Code: [Select]
// copy diagram links
foreach (EA.DiagramLink ref_dia_link in refDiagram.DiagramLinks)
{
    // what should be code here?
}

Thank you.

Danny F

  • EA User
  • **
  • Posts: 60
  • Karma: +0/-0
    • View Profile
Re: Scripting : copy diagram between packages
« Reply #5 on: October 10, 2012, 12:36:21 am »
OK  :) this seems to work
as said by Geert, you have to copy manually
DiagramObjects :
Code: [Select]
for(j=0; j<sourceDiagram.DiagramObjects.Count; j++) {
                  var sourceDiagramObject as EA.DiagramObject;
                  var destDiagramObject as EA.DiagramObject;
                  
                  sourceDiagramObject = sourceDiagram.DiagramObjects.GetAT(j);
                  destDiagramObject = destDiagram.DiagramObjects.AddNew("l=" + sourceDiagramObject.left +";r=" + sourceDiagramObject.right +";t=" + sourceDiagramObject.top +";b=" + sourceDiagramObject.bottom + ";", "");
                  destDiagramObject.ElementID = sourceDiagramObject.ElementID;
                  destDiagramObject.Style = sourceDiagramObject.Style;
                  destDiagramObject.Update();
            }
For DiagamLinks : they come with the DiagramObjects. (no addnew)
You only have to copy the properties to make them look as the original
Code: [Select]
for(j=0; j<sourceDiagram.DiagramLinks.Count; j++) {
                  var sourceDiagramLink as EA.DiagramLink;
                  var destDiagramLink as EA.DiagramLink;
                  sourceDiagramLink = sourceDiagram.DiagramLinks.GetAt(j);
                  destDiagramLink = destDiagram.DiagramLinks.GetAt(j);
                  destDiagramLink.Path = sourceDiagramLink.Path;      
                  destDiagramLink.Geometry = sourceDiagramLink.Geometry;      
                  destDiagramLink.Style = sourceDiagramLink.Style;      
                  destDiagramLink.Update();
            }

reg.

Danny
Reg.

Danny

pakcom

  • EA Novice
  • *
  • Posts: 13
  • Karma: +0/-0
    • View Profile
Re: Scripting : copy diagram between packages
« Reply #6 on: October 10, 2012, 01:32:16 am »
@Danny
Thank you for your reply.
I've tried your code, however it doesn't work.
Because destDiagram doesn't have DiagramLinks, while sourceDiagram has DiagramLinks.
It causes error out of bound.

regards,
com

Danny F

  • EA User
  • **
  • Posts: 60
  • Karma: +0/-0
    • View Profile
Re: Scripting : copy diagram between packages
« Reply #7 on: October 10, 2012, 04:48:18 pm »
Are you sure the update statement is included in your code ? :
Code: [Select]
destDiagramObject.Update();
I get an "index out of bounds" on line :
Code: [Select]
destDiagramLink = destDiagram.DiagramLinks.GetAt(j);IF (and only if) I remove above update statement

If above is not your problem : what kind of diagram is it not working for ?

reg

Danny
« Last Edit: October 10, 2012, 04:49:54 pm by dannyf »
Reg.

Danny

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: Scripting : copy diagram between packages
« Reply #8 on: October 10, 2012, 06:22:12 pm »
You have to be careful with the DiagramLinks collection.
At some point (v8 or v9) they changed the behavior of that collection.
Before it would only contain the DiagramLinks for links that had other then default style (or were once changed and then went back to the default)

Then they changed it so that it includes all links on the diagram no matter of their style.

That could explain the difference you are seeing.

Geert

pakcom

  • EA Novice
  • *
  • Posts: 13
  • Karma: +0/-0
    • View Profile
Re: Scripting : copy diagram between packages
« Reply #9 on: October 10, 2012, 06:52:42 pm »
Yes, I'm sure I code destDiagramObject.Update();

I tried to Activity Diagram, and it works.
But it doesn't work on Sequence Diagram.

I also tried another way, which is adding new connection.
Copy source connection attribute to new connection.
Set newDiagramLink.ConnectionID to new connection ID.
Then it works, but the position of diagram links will be different from original.

-com

Danny F

  • EA User
  • **
  • Posts: 60
  • Karma: +0/-0
    • View Profile
Re: Scripting : copy diagram between packages
« Reply #10 on: October 10, 2012, 08:29:31 pm »
 :( indeed : Seq diagram gives problems  ::)

Searching for a solution (I need Seq diagrams !)
Reg.

Danny

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: Scripting : copy diagram between packages
« Reply #11 on: October 10, 2012, 09:59:55 pm »
Yes, Sequence diagrams are an exception.

In order to copy a sequence diagram you actually have to copy each connector (and not only the diagramLink)

I'm not sure if it's necessary to copy the diagramLinks as well in that case.

Geert

pakcom

  • EA Novice
  • *
  • Posts: 13
  • Karma: +0/-0
    • View Profile
Re: Scripting : copy diagram between packages
« Reply #12 on: October 11, 2012, 02:03:05 am »
Hi guys..

Finally I did it. The copy sequence diagram looks like the original one.
But I have to use UPDATE query.
I have to do it because I need to copy PDATA, which I can't change it through API.
  • Add new diagram. Copy all original diagram attribute.
  • Add and copy diagram object one by one (code is similar like in the previous post above)
  • Add new connector and copy the attributes from original connector. Update new connector.
  • Add new diagram link and copy the attributes from original diagram link. Set newDiagramLink.ConnectorID = new connector ID. Update diagram link.
  • Refresh diagram and package.
From steps above I can copy sequence diagram with the connector, but the position of message line will appear different from original.
So, I use update query after that.
  • Update PDATA1 - PDATA5 like the original.
  • Don't use newConnector.Update() after that, but use newDiagramLink.Update() and newDiagram.DiagramLinks.Refresh().
  • Refresh Diagram and Repository.
By those steps, the copy diagram (including sequence diagram) will appear like the original one.

Regards,
-com

Danny F

  • EA User
  • **
  • Posts: 60
  • Karma: +0/-0
    • View Profile
Re: Scripting : copy diagram between packages
« Reply #13 on: October 11, 2012, 05:32:25 pm »
@pakcom, @geert : thank you very much - if ever we run into each other :  [smiley=beer.gif]

2  [smiley=beer.gif] if you can give me a pointer to (or explain) how the update query pdata works
I'm a newby as far as EA automisation goes - but learning at a steady pace  ;)
« Last Edit: October 11, 2012, 05:33:37 pm by dannyf »
Reg.

Danny

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: Scripting : copy diagram between packages
« Reply #14 on: October 11, 2012, 05:59:16 pm »
Danny,

There are basically two ways to use SQL when working on scripts/add-ins.

You should use Repository.SQLQuery() for all operations that select data from the model without changing it
Examples from https://github.com/GeertBellekens/Enterprise-Architect-Add-in-Framework/blob/master/EAAddinFramework/EAWrappers/Model.cs
Code: [Select]
   /// generic query operation on the model.
    /// Returns results in an xml format
    public XmlDocument SQLQuery(string sqlQuery){
      XmlDocument results = new XmlDocument();
      results.LoadXml(this.wrappedModel.SQLQuery(sqlQuery));
      return results;
    }
usage example:
Code: [Select]
   internal List<Operation>getOperationsByQuery(string SQLQuery)
    {
      // get the nodes with the name "OperationID"
      XmlDocument xmlOperationIDs = this.SQLQuery(SQLQuery);
      XmlNodeList operationIDNodes = xmlOperationIDs.SelectNodes("//OperationID");
      List<Operation> operations = new List<Operation>();
      
      foreach( XmlNode operationIDNode in operationIDNodes )
      {
            int operationID;
            if (int.TryParse(operationIDNode.InnerText,out operationID))
            {
              Operation operation = this.getOperationByID(operationID) as Operation;
                if (operation != null)
                {
                         operations.Add(operation);
                }    
            }
 
      }
      return operations;
    }
and usage of that operation:
Code: [Select]
   /// <summary>
    /// gets the parameter by its GUID.
    /// This is a tricky one since EA doesn't provide a getParameterByGUID operation
    /// we have to first get the operation, then loop the pamarameters to find the one
    /// with the GUID
    /// </summary>
    /// <param name="GUID">the parameter's GUID</param>
    /// <returns>the Parameter with the given GUID</returns>
    public ParameterWrapper getParameterByGUID (string GUID)
    {
          
                //first need to get the operation for the parameter
                string getOperationSQL = @"select p.OperationID from t_operationparams p
                                                          where p.ea_guid = '" + GUID +"'";
                //first get the operation id
                List<Operation> operations = this.getOperationsByQuery(getOperationSQL);
                if (operations.Count > 0)
                {
                      // the list of operations should only contain one operation
                      Operation operation = operations[0];
                      foreach ( ParameterWrapper parameter in operation.ownedParameters) {
                            if (parameter.ID == GUID)
                            {
                                  return parameter;
                            }
                      }
                }
          //parameter not found, return null
          return null;
    }
If you want to change data however you need to use the undocumented (and unsupported) operation Repository.Execute()
Again in the same Model class I have
Code: [Select]
   internal void executeSQL(string SQLString)
    {
          this.wrappedModel.Execute(SQLString);
    }
which is used by
https://github.com/GeertBellekens/Enterprise-Architect-Add-in-Framework/blob/master/EAAddinFramework/EASpecific/WorkingSet.cs
Code: [Select]
           /// <summary>
            /// copy the workingset tot the given user
            /// </summary>
            /// <param name="user">the user to copy the working set to</param>
            /// <param name="overwrite">if true then the first workingset found with the same name
            /// for the given user will be overwritten</param>
            public void copyToUser(User user, bool overwrite)
            {
                  if (overwrite)
                  {
                        //check if a workingset with the same name already exists
                        WorkingSet workingSetToOverwrite = this.model.workingSets.Find(w =>
                                                                            w.user != null
                                                                            && w.user.login == user.login
                                                                            && w.name == this.name);
                        if (workingSetToOverwrite != null)
                        {
                              workingSetToOverwrite.delete();
                        }
                  }
                  string insertQuery = @"insert into t_document (DocID,DocName, Notes, Style,ElementID, ElementType,StrContent,BinContent,DocType,Author,DocDate )
                                                select '"+Guid.NewGuid().ToString("B")+@"',d.DocName, d.Notes, d.Style,
                                                d.ElementID, d.ElementType,d.StrContent,d.BinContent,d.DocType,'" + user.fullName + @"',d.DocDate from t_document d
                                                where d.DocID like '"+this.ID+"'";
                  this.model.executeSQL(insertQuery);

            }

Geert