UNPKG

5.09 kBJavaScriptView Raw
1
2//
3// # IperGraph
4//
5
6var _ = require('underscore')
7
8var IperEdge = require('./IperEdge')
9 , IperNode = require('./IperNode')
10
11//
12// ## Constructor
13//
14
15function IperGraph () {
16
17 var args = arguments[0] || {}
18
19 //
20 // ## Attributes
21 //
22
23 //
24 // ### edges
25 //
26
27 Object.defineProperty(this, 'edges', {
28 enumerable: true,
29 value: []
30 })
31
32 //
33 // ### nodes
34 //
35
36 Object.defineProperty(this, 'nodes', {
37 enumerable: true,
38 value: []
39 })
40
41 /* TODO
42 //
43 // ### rank
44 //
45
46 Object.defineProperty(this, 'rank', {value: {}})
47 */
48
49 /* try to load data passed to constructor */
50 try {
51 this.load( {
52 edges: args.edges,
53 nodes: args.nodes
54 })
55 }
56 catch (err) { throw err }
57}
58
59//
60// ## Methods
61//
62
63//
64// ### check(data)
65//
66// **TODO**: vedi se riesco a referenziare la funzione load qui sotto nella documentazione
67// This method is used by load to check data is valid
68// ma può essere usata anche esternamente come metodo statico
69// dovrebbe essere statico ma ereditabile
70//
71
72
73//
74// Given an object with the following format
75//
76// ```
77// {
78// nodes: [
79// {
80// id: 1
81// },
82// {
83// id: 2
84// }
85// ...
86// ],
87// edges: [
88// {
89// id: 3,
90// nodeIds: [1, 2]
91// }
92// ...
93// ]
94// }
95// ```
96//
97// performs the followings data checks
98//
99
100function check(data) {
101 var edges = data.edges || []
102 , nodes = data.nodes || []
103
104 var nodeIds = _.pluck(nodes, 'id')
105
106 // * ids are unique
107
108 /* TODO Da fare anche su edges e subgraph */
109
110 if (_.unique(nodeIds).length !== nodeIds.length)
111 throw new Error('duplicated node id')
112
113
114 // * edges refers to existing nodeIds
115 _.each(edges, function (edge) {
116 _.each(edge.nodeIds, function (nodeId) {
117 if (_.indexOf(nodeIds, nodeId) < 0)
118 throw new Error('invalid edge')
119 })
120 })
121
122 return true
123}
124
125IperGraph.prototype.check = check
126
127//
128// ### load(data) {#load}
129//
130
131function load(data) {
132 var self = this
133
134 /* check if data is valid */
135 try {
136 check(data)
137 }
138 catch (er) { throw er }
139
140 var edges = data.edges
141 , nodes = data.nodes
142
143 /* store a lookup of new <--> old ids */
144 var brandNew = {}
145
146 /* create new nodes first */
147 _.each(nodes, function (node) {
148 var id = node.id
149 , opts = {}
150
151 /* remember association between old and new id */
152 brandNew[id] = self.createNode(id, opts)
153 })
154
155 /* create new edges */
156 _.each(edges, function (edge) {
157
158 var newNodeIds = []
159 , oldNodeIds = edge.nodeIds
160
161 /* loop over old node ids and get the corresponding new ids */
162 _.each(oldNodeIds, function (id) {
163 newNodeIds.push(brandNew[id])
164 })
165
166 /* use new ids to create a new edge */
167 self.createEdge(newNodeIds)
168 })
169}
170
171IperGraph.prototype.load = load
172
173//
174// ### createEdge()
175//
176
177function createEdge(nodeIds) {
178 var edge = new IperEdge(this, nodeIds)
179 return edge.id
180}
181
182IperGraph.prototype.createEdge = createEdge
183
184//
185// ### createNode()
186//
187
188function createNode(opts) {
189 var node = new IperNode(this, opts)
190
191 // * returns node id
192 return node.id
193}
194
195IperGraph.prototype.createNode = createNode
196
197//
198// ### getEdge()
199//
200
201function getEdge(id) {
202 var edgeFound
203
204 _.each(this.edges, function (edge) {
205 if (id === edge.id)
206 edgeFound = edge
207 })
208
209 if (edgeFound)
210 return edgeFound
211 else
212 throw new Error('edge not found')
213}
214
215IperGraph.prototype.getEdge = getEdge
216
217//
218// ### getNode()
219//
220
221function getNode(id) {
222 var nodeFound
223
224 _.each(this.nodes, function (node) {
225 if (id === node.id)
226 nodeFound = node
227 })
228
229 if (nodeFound)
230 return nodeFound
231 else
232 throw new Error('node not found')
233}
234
235IperGraph.prototype.getNode = getNode
236
237//
238// ### removeEdge()
239//
240
241function removeEdge(id) {
242 var self = this;
243
244 _.each(self.edges, function (edge, index) {
245
246 if (id === edge.id)
247 self.edges.splice(index, 1)
248 })
249}
250
251IperGraph.prototype.removeEdge = removeEdge
252
253//
254// ### removeNode()
255//
256// Removes node by given id
257//
258//
259//```
260//graph.removeNode(nodeId)
261//```
262//
263
264function removeNode(id) {
265 var self = this
266
267 var edges = this.edges
268 , nodes = this.nodes
269
270 /* TODO fai try getNode per fare throw di node not found */
271
272 /* loop over all edges */
273 _.each(edges, function (edge) {
274
275 /* loop over edge nodeIds */
276 _.each(edge.nodeIds, function (nodeId, index) {
277
278 /* drop nodeId from edges linked to removed node */
279 if (id === nodeId)
280 edge.nodeIds.splice(index, 1)
281 })
282
283 /* remove orphan edges */
284 /* TODO in realta non sarebbe 2 ma il rank dell' edge */
285 if (edge.nodeIds.length < 2)
286 edge.remove()
287 })
288
289 _.each(nodes, function (node, index) {
290 if (id === node.id)
291 self.nodes.splice(index, 1)
292 })
293}
294
295IperGraph.prototype.removeNode = removeNode
296
297module.exports = IperGraph
298