Created
March 10, 2022 08:37
-
-
Save christhearchitect/49e4f3e405d42f83c3df9d3d05df6629 to your computer and use it in GitHub Desktop.
#jArchi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* This script reads a CSV file with the following columns: Relationship type, Relationship name, Source Element name, Source Element type", Target Element name, Target Element type, {<property-name>}. Each row represents one element along with its main attributes, | |
* and is loaded into the current model according to these rules: | |
* -- if the relationship (defined by the Name/Type pair) exists in the current model, its properties are updated (subject to "overwriteAttributes" and "blankMeansDontChange" below) | |
* -- if not, a new relationship is created (along with its properties) | |
* -- the Type field is mandatory, but Name and properties can be empty | |
* -- if a relationship in the CSV matches several existing relationship, it is ignored | |
* -- the script does not create any views or visual diagram objects for the imported elements; therefore, it cannot load any visual attributes, such as style or label | |
* | |
* Author: christhearchitect | |
* Version: 0.2 | |
* | |
* (credits: some code from https://gist.github.com/smileham/1e57a5946235e780dee5a824f664aa3d used to read CSV ) | |
* | |
*/ | |
console.clear(); | |
console.log("ImportRelationshipsFromCSV\n--------------------------\n"); | |
// Constants: change them to suit your needs | |
var headerColumns = ["Relationship type", "Relationship name", "Source Element name", "Source Element type", "Target Element name", "Target Element type"]; // will be checked agains actual CSV | |
var addSourceProp = true; // if true, property "Source = <filename>" will be added to every element created | |
var overwriteAttributes = true; // if an element already exists, its Documentation and Properties attributes in the CSV will overwrite those in the model | |
var blankMeansDontChange = true; // when updating attributes, blank ("") attributes are left unchanged even if overwriteAttributes is true | |
var debug = false; | |
// End of Constants | |
var newRelCount = 0; | |
var updRelCount = 0; | |
//TBD: check that current model is defined | |
load(__DIR__ + "lib/papaparse.min.js"); | |
debug?console.log("// Loaded library: PapaParse"):null; | |
var filePath = window.promptOpenFile({ title: "Open CSV file", filterExtensions: ["*.CSV"], fileName: "" }); | |
if (filePath) { | |
var fileName = filePath.replace(/^.*(\\|\/|\:)/, ''); | |
var FileReader = Java.type("java.io.FileReader"); | |
var Types = Java.type("java.nio.charset.StandardCharsets"); | |
var theCSVFile = new FileReader(filePath,Types.UTF_8); | |
var theCSV =""; | |
var data = theCSVFile.read(); | |
console.log("> Loading file, please wait..."); | |
while(data != -1) { | |
var theCharacter = String.fromCharCode(data); | |
theCSV+=theCharacter; | |
data = theCSVFile.read(); | |
} | |
theCSVFile.close(); | |
console.log("> File Loaded"); | |
theDataFile = Papa.parse(theCSV); | |
theData = theDataFile.data; | |
console.log("> Parsing Complete"); | |
debug?console.log("// Actual CSV header : '"+theData[0].slice(0,headerColumns.length)+"'\n// Expected header: '"+headerColumns+"'"):null; | |
if (theData[0].slice(0,headerColumns.length).toString()==headerColumns.toString()) { | |
// Header matches the expected columns | |
for (i=1; i<theData.length; i++) { | |
// Iterate over each data row and create the corresponding new relationships | |
debug?console.log("// CSV data",i,"=",theData[i],theData[i][0].length==0?"(skipping)":"(processing)"):null; | |
if (theData[i][0].length>0) { | |
var curRelType = theData[i][0]; | |
var curRelName = theData[i][1]; | |
var curSourceName = theData[i][2]; | |
var curSourceType = theData[i][3]; | |
var curTargetName = theData[i][4]; | |
var curTargetType = theData[i][5]; | |
var curSourceMatch = $("."+curSourceName).filter(curSourceType); | |
var curTargetMatch = $("."+curTargetName).filter(curTargetType); | |
if (curSourceMatch.length==0 || curTargetMatch.length==0) { | |
console.log("> Error in CSV row "+i+": no match for one of the ends ("+curSourceType+":"+curSourceName+" or "+curTargetType+":"+curTargetName+") -- no action"); | |
} else if (curSourceMatch.length>1 || curTargetMatch.length>1) { | |
console.log("> Error in CSV row "+i+": more than one match for one of the ends ("+curSourceType+":"+curSourceName+" or "+curTargetType+":"+curTargetName+") -- no action"); | |
} else { // curSourceMatch.length==1 && // curTargetMatch.length==1 | |
var curOutRels = $("."+curSourceName).outRels().filter(curRelType).filter("."+curRelName); | |
var curInRels = $("."+curTargetName).inRels().filter(curRelType).filter("."+curRelName); | |
debug?console.log("// outRels =",curOutRels):null; | |
debug?console.log("// inRels =",curInRels):null; | |
// Compute intersection of both sets of relationships: | |
var curExistingRels = curOutRels.filter(function(o) { return curInRels.filter(o.type).filter("."+o.name).length>0; }); | |
debug?console.log("// Existing relationships FROM",curSourceType+":"+curSourceName,"TO",curTargetType+":"+curTargetName,"=",curExistingRels):null; | |
if (curExistingRels.length==0) { | |
// Create new relationship | |
debug?console.log("// Creating new relationship",curRelType+":"+curRelName,"FROM",curSourceType+":"+curSourceName,"TO",curTargetType+":"+curTargetName,"=",curExistingRels):null; | |
var curRelationship = model.createRelationship(curRelType,curRelName,curSourceMatch[0],curTargetMatch[0]); | |
if (addSourceProp) {curRelationship.prop("Source","CSV import from '"+fileName+"'")}; | |
newRelCount++; | |
} else { | |
var curRelationship = curExistingRels[0]; | |
}; | |
if (curExistingRels.length==0 || (curExistingRels.length==1 && overwriteAttributes)) { | |
// In both cases, we need to update the relationship's properties | |
for (p=headerColumns.length; p<theData[i].length; p++) { | |
// Set any valid properties defined in the CSV (skip if the column header is "") | |
if (theData[0][p].length>0) { | |
if (theData[i][p]=="" && blankMeansDontChange) { | |
debug?console.log("// Skipping blank property",theData[0][p]):null; | |
} else { | |
debug?console.log("// Setting property "+theData[0][p]+" = '"+theData[i][p]+"'"):null; | |
curRelationship.prop(theData[0][p],theData[i][p]); | |
} | |
} | |
} | |
updRelCount++; // note that new relationships are also counted here -- we'll correct this further down the line | |
} else { | |
// More than one relationship: skip update | |
console.log("> Error in CSV row "+i+": more than one match for the relationship ("+curRelType+":"+curRelName+") -- no action"); | |
} | |
} | |
} | |
} | |
updRelCount -= newRelCount; // Because of the above if/else sequence, uprRelCount was also incremented after a new relationship was created | |
console.log("\n>", newRelCount, "new elements created\n>", updRelCount, "existing elements "+(overwriteAttributes?"updated":"skipped")); | |
} else { | |
console.log("> Error: the header in", "'"+filePath+"' does not match expected columns "+headerColumns); | |
} | |
} else { | |
console.log("> Cancelled"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment