Error in adding relationship on view

Started by Gerald Groot Roessink, November 27, 2022, 13:34:58 PM

Previous topic - Next topic

Gerald Groot Roessink

Hi,
Created a simple script to make a copy of an existing view. It works voor elements, but when I copy the relationships, the scripts crashes with a type-error on linenumber 43.


selection.filter("view").each(function(view) {

    var viw = model.createArchimateView(view.name+"_copy");
viw.documentation = view.documentation;
viw.viewpoint = "layered";
console.log("Added view - ", view.model, view.name, view.documentation);

// add visual elements
const visuals = $(view).find('element'); // This gets the list of visual objects on view
for(var ve = 0; ve < visuals.length; ve++) {
var obj=visuals[ve].concept;
var x = visuals[ve].bounds.x;
var y = visuals[ve].bounds.y;
var width = visuals[ve].bounds.width;
var height = visuals[ve].bounds.height;
viw.add(obj, x, y, width, height); 
console.log( obj, x, y, width, height); 
};

// add visual relationships
const visualrels = $(view).find('relationship'); // This gets the list of visual relations on view
for(var vr = 0; vr < visualrels.length; vr++) {
var rel =  visualrels[vr].concept
var obj1 = visualrels[vr].concept.source; //its source
var obj2 = visualrels[vr].concept.target; //its target
viw.add(rel, obj1, obj2); 

};

});


I believe I did exactly  the same as the example-script Create Views and Visual Objects, more general. What am I doing wrong?

Thanks, Gerald

   

Jean-Baptiste Sarrodie

Hi,

obj1 and obj2 must be visual objects, not model concepts ;-)
(that's because the same model concept can appear several time in a same view)

Regards,

JB
If you value and use Archi, please consider making a donation!
Ask your ArchiMate related questions to the ArchiMate Community's Discussion Board.

Gerald Groot Roessink

Thanks JB for the swift response. Appreciate it very much.

I took this approach: storing the id's of original visual elements and their copy in the array pairs and using array.find to lookup the visual elements on the new view copy. I believe obj1 and obj2 are visuals elements now.

However, the result is unchanged, I find the same error.

// Show output in the console
console.show();
console.clear()
console.log("> Starting copy");

selection.filter("view").each(function(view) {
        var viw = model.createArchimateView(view.name+"_copy");

    // array for storing id of original and copy in pairs.
    const  pairs = [] ;
   
    // add visual elements
    const visuals = $(view).find('element'); // This gets the list of visual objects on original view
    for(var ve = 0; ve < visuals.length; ve++) {
        var obj=visuals[ve].concept;
        var x = visuals[ve].bounds.x;
        var y = visuals[ve].bounds.y;
        var width = visuals[ve].bounds.width;
        var height = visuals[ve].bounds.height;
        obj_copy=viw.add(obj, x, y, width, height); 
        console.log( obj, x, y, width, height);
        pairs.push( {orig: visuals[ve].id,copy: obj_copy.id});
       
    };
   
        for(var i = 0; i < pairs.length; i++) {
        console.log (pairs[i]);
    }
       
    // add visual relationships
    const visualrels = $(view).find('relationship'); // This gets the list of visual relations on original view
    for(var vr = 0; vr < visualrels.length; vr++) {
        var rel = visualrels[vr].concept;
        let src_id = pairs.find(src_id => src_id.orig === visualrels[vr].source.id);  //its source - id (visual)
        let tar_id = pairs.find(tar_id => tar_id.orig === visualrels[vr].target.id);  //its target - id (visual)
        console.log (rel, src_id.copy, tar_id.copy);

        let obj1 = $("#"+src_id.copy); // find the visual element with id
        let obj2 = $("#"+tar_id.copy); // find the visual element with id
        console.log (rel, obj1, obj2);

        var connection=viw.add(rel, obj1, obj2); 
    };
});


Again, any suggestions?
Thanks, Gerald




Jean-Baptiste Sarrodie

Hi,

You can't find visual objects by #id. Your 'Pairs' list should point to objects, not ids.

So:
pairs.push( {orig: visuals[ve].id,copy: obj_copy.id});

should become:
pairs.push( {orig: visuals[ve].id,copy: obj_copy});

And change the second part accordingly.

Btw, it is usually easier to declare pairs as an object and use the id of the source visual object as key:
pairs[visuals[ve].id] = obj_copy;

So (with other small changes) your code becomes:
// Show output in the console
console.show();
console.clear()
console.log("> Starting copy");

selection.filter("view").each(function(view) {
    var viw = model.createArchimateView(view.name+"_copy");

    // array for storing id of original and copy in pairs.
    var  pairs = {} ;

    // add visual elements
    $(view).find('element').each(function(ve) {
        var obj=ve.concept;
        var bounds = ve.bounds;
        obj_copy=viw.add(obj, bounds.x, bounds.y, bounds.width, bounds.height);
        console.log( obj, bounds.x, bounds.y, bounds.width, bounds.height);
        pairs[ve.id] = obj_copy;
    });
 
    console.log (pairs);

     
    // add visual relationships
    $(view).find('relationship').each(function(vr) {
        var rel = vr.concept;
        var connection=viw.add(rel, pairs[vr.source.id], pairs[vr.target.id]);
    });
});

Next challenges for you: manager relationships to relationships, and bendpoints :-)

Regards,

JB
If you value and use Archi, please consider making a donation!
Ask your ArchiMate related questions to the ArchiMate Community's Discussion Board.

Gerald Groot Roessink

Many thanks. I am going to use this tomorrow. I'll get back.
Gerald

Gerald Groot Roessink

It works. You have improved my code a lot.

Jean-Baptiste Sarrodie

If you value and use Archi, please consider making a donation!
Ask your ArchiMate related questions to the ArchiMate Community's Discussion Board.

mibnf

Quote from: Gerald Groot Roessink on November 28, 2022, 09:29:15 AMIt works. You have improved my code a lot.


Hi Gerald,

I'm looking for something similar. Any chance you can share your work?

Kind regards,
Michael

Gerald Groot Roessink

Hi Michael,
This is the script I am using to make an copy of an existing view. It is basic. Not all properties of visual objects are copied but can be added.
Good luck.
Gerald
/*
 * Copy a View
 *
 * Copy visual elements and relations from the original view to a newly created view
 *
 * (c) 2022  Archi community
 *
 * This work is licensed under the HUMANS Licence described below.
 *
 * The HUMANS (Help Us Make Archi Noteworthy & Sustainable) licence goal is to bring happiness
 * to both Archi users and developers.
 *
 * The only restrictions that apply are:
 *  - You can't redistribute this script.
 *  - You can't use this script for commercial purposes
 *
 */

 
// Show output in the console
console.show();
console.clear();

var select=false;
selection.filter("view").each(function(view) {

    var view_copy = model.createArchimateView(view.name+"_copy");
    view_copy.documentation = view.documentation;
    view_copy.viewpoint = "layered";
    console.log("Copied view - ", view.name, "  --> ", view_copy.name);   

    // Copy properties belonging to view.
    for(var j = 0; j < $(view).prop().length; j++) {
        var key = $(view).prop()[j];
        var val = $(view).prop($(view).prop()[j]);            
        view_copy.prop(key, val );
    };

    // add objects like grouping
    // note: it should also apply to notes but that isn't working
    var  obj_copy = {} ;
    $(view).find('object').each(function(vo) {
        var obj=vo.concept;
        var bounds = vo.bounds;
       
        //calculate the absolute xy coordinates of nested elements.
        var x=bounds.x;
        var y=bounds.y;
        $(vo).parents().not('folder').not('archimate-diagram-model').each(function(mum){
            x=x+mum.bounds.x;
            y=y+mum.bounds.y;
        });
       
        //declare copy of visual as an object and use the id of the source visual object as key
        obj_copy[vo.id]=view_copy.createObject(obj, x, y, bounds.width, bounds.height, "true"); //autoNest=true

        // if need be: add other attributes
       
    });
   
    // add visual elements
    var  obj_copy = {} ;
    $(view).find('element').each(function(ve) {
        var obj=ve.concept;
        var bounds = ve.bounds;
       
        //calculate the absolute xy coordinates of nested elements.
        var x=bounds.x;
        var y=bounds.y;
        $(ve).parents().not('folder').not('archimate-diagram-model').each(function(mum){
            x=x+mum.bounds.x;
            y=y+mum.bounds.y;
        });
       
        //declare copy of visual as an object and use the id of the source visual object as key
        obj_copy[ve.id]=view_copy.add(obj, x, y, bounds.width, bounds.height, "true"); //autoNest=true
        // if need be: add other attributes

    });
 
  
    // add visual relationships
    $(view).find('relationship').each(function(vr) {
        var rel = vr.concept;
        var connection=view_copy.add(rel, obj_copy[vr.source.id], obj_copy[vr.target.id]);
   
        // bending of relations.
        var bendpoints = vr.getRelativeBendpoints();
        for(var k = 0; k < bendpoints.length; k++) {
            connection.addRelativeBendpoint(bendpoints[k],k)
        };   

        // if need be: add other attributes
        // may be later: relationship to relationship

    });
    select=true;
});



if(!select) {
    console.log("Nothing to be copied. Please select a view");
}