-
Notifications
You must be signed in to change notification settings - Fork 0
/
graph-marking.js
120 lines (100 loc) · 4.11 KB
/
graph-marking.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
// (name: String, collection: Mongo.Collection) => String|undefined
Mongo.Collection.prototype.getMarkingField = function(name, collection) {
if (!this._marking || !this._marking[name])
return undefined;
else return this._marking[name]._in[collection._ref];
};
// [new] (graph: Mongo.Collection, name: String, options: Options)
Shuttler.GraphMarking = function(graph, name, options) {
var marking = this;
this._name = name;
if (!(this instanceof Shuttler.GraphMarking))
return new Shuttler.GraphMarking(graph, name, options);
if (!(graph instanceof Mongo.Collection) || !graph.isGraph)
throw new Meteor.Error('Collection '+graph._ref+' is not a graph.');
if (graph._marking && graph._marking[name])
throw new Meteor.Error('Graph marking with name '+name+' already defined.');
// Mongo.Collection
this._graph = graph;
// { (collection: String): (field: String) }
this._in = {};
if (!options) var options = {};
var contextOptions = Shuttler.GraphMarking.OptionsSchema.newContext();
Shuttler.GraphMarking.OptionsSchema.clean(options);
if (!contextOptions.validate(options))
throw new Meteor.Error(contextOptions.keyErrorMessage(contextOptions.invalidKeys()[0].name));
this._options = options;
if (!graph._marking)
graph._marking = {};
graph._marking[this._name] = marking;
};
// (collection: Mongo.Collection, field: String) => Shuttler.GraphMarking
Shuttler.GraphMarking.prototype.in = function(collection, field) {
// { (field: String): (markingInstance: Shuttler.GraphMarking) }
if (!collection._markedByGraphs)
collection._markedByGraphs = {};
collection._markedByGraphs[field] = this;
// { (collection: String): (field: String) }
this._in[collection._ref] = field;
return this;
};
// () => Shuttler.GraphMarking
Shuttler.GraphMarking.prototype.watch = function() {
var marking = this;
this._graph.after.link(function(userId, unlinked, linked, fieldNames, modifier, options) {
marking._options.afterLink.call(this, userId, unlinked, linked, fieldNames, modifier, options, marking);
});
this._graph.after.unlink(function(userId, unlinked, linked, fieldNames, modifier, options) {
marking._options.afterUnlink.call(this, userId, unlinked, linked, fieldNames, modifier, options, marking);
});
};
Shuttler.GraphMarking.byTarget = {
afterLink: function(userId, unlinked, linked, fieldNames, modifier, options, marking) {
var document = linked.target();
var collection = document.Collection();
var field = marking._graph.getMarkingField(marking._name, collection);
if (field)
collection.update(document._id, { $addToSet: { [field]: linked['_source'] } });
},
afterUnlink: function(userId, unlinked, linked, fieldNames, modifier, options, marking) {
var document = unlinked.target();
var collection = document.Collection();
var others = marking._graph.links.find(unlinked._source, unlinked._target)
if (!others.count()) {
var field = marking._graph.getMarkingField(marking._name, collection);
if (field)
collection.update(document._id, { $pull: { [field]: unlinked['_source'] } });
}
}
};
Shuttler.GraphMarking.bySource = {
afterLink: function(userId, unlinked, linked, fieldNames, modifier, options, marking) {
var document = linked.source();
var collection = document.Collection();
var field = marking._graph.getMarkingField(marking._name, collection);
if (field)
collection.update(document._id, { $addToSet: { [field]: linked['_target'] } });
},
afterUnlink: function(userId, unlinked, linked, fieldNames, modifier, options, marking) {
var document = unlinked.source();
var collection = document.Collection();
var others = marking._graph.links.find(unlinked._source, unlinked._target)
if (!others.count()) {
var field = marking._graph.getMarkingField(marking._name, collection);
if (field)
collection.update(document._id, { $pull: { [field]: unlinked['_target'] } });
}
}
};
Shuttler.GraphMarking.OptionsSchema = new SimpleSchema({
afterLink: {
type: Function,
optional: true,
defaultValue: Shuttler.GraphMarking.byTarget.afterLink
},
afterUnlink: {
type: Function,
optional: true,
defaultValue: Shuttler.GraphMarking.byTarget.afterUnlink
}
});