-
Notifications
You must be signed in to change notification settings - Fork 2
/
dependencies.js
134 lines (116 loc) · 4.89 KB
/
dependencies.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* TODO: produce a graph, showing the dependency diagram
* a node may be
* - desired: bool
* - satisfied: bool
*
* a node group is an ordered set of nodes.
* if node in the group is satisfied, then the entire group is satisfied.
* if the group is not satisfied, then the first node in the group is desired.
*
* CS: https://en.wikipedia.org/wiki/Topological_sorting
*/
// ---------------------------------------------------------------------------------------------------------------- desiredTemplates_
// dumps dependency graph into a tab called Execution
// deletes everything in the Execution tab
// writes in all the templates needed to satisfy the current sheet
// writes in all the signatories as well
function computeDependencies() {
var sheet = SpreadsheetApp.getActiveSheet();
// TODO: add support for running in Controller mode
var entitiesByName = {};
var readRows_ = new readRows(sheet, entitiesByName,0);
deLog(["computeDependencies calling depGraph()",5]);
var dg = new depGraph(readRows_);
// output to Execution sheet
var executionName = "Execution";
var execution = sheet.getParent().getSheetByName(executionName)
|| sheet.getParent().insertSheet(executionName, sheet.getIndex());
execution.clear();
var cell = execution.getRange(2,2,1,1);
cell.setValue(dg.as_string());
}
/*
* We describe the nodes of the dependency graph in some detail here.
* Later, the depGraph library takes care of computing the graph.
* At run-time, we calculate which dependences are already satisfied.
* We then display a list of templates which are needed to execute a
* given action.
*
* @constructor
* @param {Object} readRows_ - a readRows object containing a given sheet
* @param {string} templateName - the name of a template named by the sheet
*
* returns an object containing children and parties
*/
function depGraph(readRows_, templateName) {
deLog("depGraph(%s, %s): starting", readRows_.sheetname, templateName);
this.children = [];
this.normal_parties = [];
this.explode_parties = [];
this.name = "";
if (! templateName) { // the dependencies for a sheet are the dependencies for all of its suitable templates
this.name = readRows_.sheetname;
this.children = readRows_.suitableTemplates.map(function(t){return new depGraph(readRows_, t.name)});
deLog(["sheet-level depGraph has %s children.", this.children.length],5);
}
else { // the dependencies for a template are identified in config under the "requires" tree
this.name = templateName;
if (readRows_.config.templates.dict2[templateName] &&
readRows_.config.templates.dict2[templateName].requires &&
readRows_.config.templates.dict2[templateName].requires.length) {
var children = readRows_.config.templates.dict2[templateName].requires;
deLog(["config.templates.%s.requires = %s",templateName,children]);
this.children = children.map (function(tname) {
if (tname.match(/ : /)) { // reference to foreign table
deLog(["reference to foreign table %s -- TODO FIXME", tname]);
return;
}
return new depGraph(readRows_,tname);
}
);
}
else { deLog(["%s does not require any others", templateName]); }
var that = this;
var callback = function(sourceTemplates, entity, rcpts, explosion) { // this is a callback run within the docsetEmails_ object.
var to_emails = rcpts[0];
var cc_emails = rcpts[1];
var to_parties= rcpts[2];
var cc_parties= rcpts[3];
deLog(["docsetEmails callback: rcpts to_emails = %s", to_emails], 6);
deLog(["docsetEmails callback: rcpts cc_emails = %s", cc_emails], 6);
deLog(["docsetEmails callback: rcpts to_parties = %s", to_parties], 6);
deLog(["docsetEmails callback: rcpts cc_parties = %s", cc_parties], 6);
if (explosion) {
// that.explode_parties = that.explode_parties.concat(to_parties.map(function(p){return [p.name, p.email]}))
that.explode_parties = that.explode_parties.concat(to_emails);
}
else {
// that.normal_parties = that.normal_parties.concat(to_parties.map(function(p){return [p.name, p.email]}))
that.normal_parties = that.normal_parties.concat(to_emails);
}
deLog(["docsetEmails callback: keep your eye on the prize -- the goal is to populate the dependency's signature parties"]);
};
var docsetEmails_ = readRows_.docsetEmails;
deLog(["calling docsetEmails.normal(callback)"]);
docsetEmails_.normal(callback);
deLog(["calling docsetEmails.explode(callback)"]);
docsetEmails_.explode(callback);
}
}
depGraph.prototype.as_string = function() {
return JSON.stringify(this.as_array());
return this.as_array().join("\n");
};
depGraph.prototype.as_array = function(depth) {
depth = depth || 0;
var mya = [];
var prefix = Array(depth).join(" ");
mya.push(prefix + "# " + this.name);
for (var i in this.children) {
var child = this.children[i];
mya.push(prefix + child.name + " -> " + this.name);
mya = mya.concat(child.as_array(depth+1));
}
mya.push("");
return mya;
};