Vuo 2.4.2
Loading...
Searching...
No Matches
VuoCompilerCompositionDiff.cc
Go to the documentation of this file.
1
11
12#include "VuoCompilerCable.hh"
14#include "VuoCompilerGraph.hh"
15#include "VuoCompilerNode.hh"
17#include "VuoCable.hh"
18#include "VuoComposition.hh"
19#include "VuoNode.hh"
20#include "VuoNodeClass.hh"
21#include "VuoPort.hh"
22#include "VuoPublishedPort.hh"
23#include "VuoStringUtilities.hh"
24
112string VuoCompilerCompositionDiff::diff(const string &oldCompositionGraphvizDeclaration, VuoCompilerComposition *newComposition,
113 VuoCompiler *compiler)
114{
115 VuoCompilerComposition *oldComposition = VuoCompilerComposition::newCompositionFromGraphvizDeclaration(oldCompositionGraphvizDeclaration, compiler);
116 json_object *diffJson = json_object_new_array();
117
118 diff(oldComposition, newComposition, "", "", VuoCompilerComposition::topLevelCompositionIdentifier, compiler, diffJson);
119
120 delete oldComposition;
121
122 string diffString = json_object_to_json_string_ext(diffJson, JSON_C_TO_STRING_PLAIN);
123 VuoStringUtilities::replaceAll(diffString, "\\/", "/");
124 json_object_put(diffJson);
125 return diffString;
126}
127
132 const string &parentCompositionIdentifier, const string &parentCompositionPath,
133 const string &unqualifiedCompositionIdentifier,
134 VuoCompiler *compiler, json_object *diffJson)
135{
136 string compositionIdentifier = (parentCompositionIdentifier.empty() ?
137 unqualifiedCompositionIdentifier :
138 parentCompositionIdentifier + "/" + unqualifiedCompositionIdentifier);
139 string compositionPath = (parentCompositionPath.empty() ?
140 unqualifiedCompositionIdentifier :
141 parentCompositionPath + "/" + unqualifiedCompositionIdentifier);
142
143 // Diff nodes that have been added or removed with no replacement or refactoring.
144
145 set<VuoNode *> oldNodes;
146 set<VuoNode *> newNodes;
147 if (oldComposition)
148 oldNodes = oldComposition->getBase()->getNodes();
149 if (newComposition)
150 newNodes = newComposition->getBase()->getNodes();
151
152 map<string, VuoNode *> oldNodeForIdentifier;
153 map<string, VuoNode *> newNodeForIdentifier;
154 map<string, pair<VuoNode *, VuoNode *> > oldAndNewNodeForIdentifier;
155 for (set<VuoNode *>::iterator i = oldNodes.begin(); i != oldNodes.end(); ++i)
156 {
157 string identifier = (*i)->getCompiler()->getGraphvizIdentifier();
158 oldNodeForIdentifier[identifier] = *i;
159 oldAndNewNodeForIdentifier[identifier].first = *i;
160 }
161 for (set<VuoNode *>::iterator i = newNodes.begin(); i != newNodes.end(); ++i)
162 {
163 string identifier = (*i)->getCompiler()->getGraphvizIdentifier();
164 newNodeForIdentifier[identifier] = *i;
165 oldAndNewNodeForIdentifier[identifier].second = *i;
166 }
167
168 for (map<string, VuoNode *>::iterator oldNodeIter = oldNodeForIdentifier.begin(); oldNodeIter != oldNodeForIdentifier.end(); ++oldNodeIter)
169 {
170 if (newNodeForIdentifier.find(oldNodeIter->first) == newNodeForIdentifier.end() &&
171 ! isNodeBeingReplaced(compositionIdentifier, oldNodeIter->first) &&
172 ! isNodeBeingRefactored(parentCompositionIdentifier, unqualifiedCompositionIdentifier, oldNodeIter->first))
173 {
174 // { "remove" : "<composition path>/<node identifier>" }
175 json_object *remove = json_object_new_object();
176 json_object *nodePath = json_object_new_string((compositionPath + "/" + oldNodeIter->first).c_str());
177 json_object_object_add(remove, "remove", nodePath);
178 json_object_array_add(diffJson, remove);
179 }
180 }
181 for (map<string, VuoNode *>::iterator newNodeIter = newNodeForIdentifier.begin(); newNodeIter != newNodeForIdentifier.end(); ++newNodeIter)
182 {
183 if (oldNodeForIdentifier.find(newNodeIter->first) == oldNodeForIdentifier.end() &&
184 ! isNodeReplacingAnother(compositionIdentifier, newNodeIter->first) &&
185 ! isNodeBeingRefactored(parentCompositionIdentifier, unqualifiedCompositionIdentifier, newNodeIter->first))
186 {
187 // { "add" : "<composition path>/<node identifier>" }
188 json_object *add = json_object_new_object();
189 json_object *nodePath = json_object_new_string((compositionPath + "/" + newNodeIter->first).c_str());
190 json_object_object_add(add, "add", nodePath);
191 json_object_array_add(diffJson, add);
192 }
193 }
194
195 // If we're inside a subcomposition instance that is being added/removed, add/remove the manually firable trigger node.
196
197 if (! oldComposition)
198 {
199 json_object *add = json_object_new_object();
200 json_object *nodePath = json_object_new_string((compositionPath + "/" + VuoCompilerGraph::getManuallyFirableTriggerNodeIdentifier()).c_str());
201 json_object_object_add(add, "add", nodePath);
202 json_object_array_add(diffJson, add);
203 }
204 if (! newComposition)
205 {
206 json_object *remove = json_object_new_object();
207 json_object *nodePath = json_object_new_string((compositionPath + "/" + VuoCompilerGraph::getManuallyFirableTriggerNodeIdentifier()).c_str());
208 json_object_object_add(remove, "remove", nodePath);
209 json_object_array_add(diffJson, remove);
210 }
211
212 // Diff nodes that have been refactored.
213
214 auto buildMovePath = [](const Refactoring &r, const string &nodeIdentifier)
215 {
216 return r.compositionIdentifier + "/" + nodeIdentifier;
217 };
218 auto buildToPath = [](const Refactoring &r, const string &nodeIdentifier)
219 {
220 return r.compositionIdentifier + "/" + r.unqualifiedSubcompositionIdentifier + "/" + nodeIdentifier;
221 };
222
223 for (const Refactoring &r : refactorings)
224 {
225 if (compositionIdentifier == r.compositionIdentifier)
226 {
227 for (const string &nodeIdentifier : r.nodeIdentifiers)
228 {
229 // { "move" : "<composition path>/<node identifier>", "to" : "<subcomposition path>/<node identifier>",
230 json_object *move = json_object_new_object();
231 json_object *oldNodePath = json_object_new_string(buildMovePath(r, nodeIdentifier).c_str());
232 json_object_object_add(move, "move", oldNodePath);
233 json_object *newNodePath = json_object_new_string(buildToPath(r, nodeIdentifier).c_str());
234 json_object_object_add(move, "to", newNodePath);
235 json_object_array_add(diffJson, move);
236 }
237 }
238 else if (parentCompositionIdentifier == r.compositionIdentifier && unqualifiedCompositionIdentifier == r.unqualifiedSubcompositionIdentifier)
239 {
240 for (const string &nodeIdentifier : r.nodeIdentifiers)
241 {
242 // "ports" : [
243 // { "copy" : "<port identifier>", "to" : "<composition path>/<node identifier>:<port identifier>" },
244 // { "copy" : "<port identifier>", "to" : "<composition path>/<node identifier>:<port identifier>" },
245 // ... ] }
246
247 json_object *move = nullptr;
248 int length = json_object_array_length(diffJson);
249 for (int i = 0; i < length; ++i)
250 {
251 json_object *curr = json_object_array_get_idx(diffJson, i);
252 json_object *moveNodePath = nullptr;
253 json_object *toNodePath = nullptr;
254
255 if (json_object_object_get_ex(curr, "move", &moveNodePath) && json_object_object_get_ex(curr, "to", &toNodePath) &&
256 buildMovePath(r, nodeIdentifier) == json_object_get_string(moveNodePath) &&
257 buildToPath(r, nodeIdentifier) == json_object_get_string(toNodePath))
258 {
259 move = curr;
260 break;
261 }
262 }
263
264 json_object *ports = json_object_new_array();
265 for (VuoPort *internalPort : newNodeForIdentifier[nodeIdentifier]->getInputPorts())
266 {
267 for (VuoCable *cable : internalPort->getConnectedCables())
268 {
269 if (cable->isPublished() && cable->getCompiler()->carriesData())
270 {
271 json_object *portObj = json_object_new_object();
272 json_object *portNameOnMovedNode = json_object_new_string(internalPort->getClass()->getName().c_str());
273 json_object_object_add(portObj, "copy", portNameOnMovedNode);
274 json_object *portNameOnSubcompositionNode = json_object_new_string((r.compositionIdentifier + "/" + r.unqualifiedSubcompositionIdentifier + ":" + cable->getFromPort()->getClass()->getName()).c_str());
275 json_object_object_add(portObj, "to", portNameOnSubcompositionNode);
276 json_object_array_add(ports, portObj);
277 }
278 }
279 }
280
281 json_object_object_add(move, "ports", ports);
282 }
283 }
284 }
285
286 auto nodeReplacementExists = [this](const string &compositionIdentifier, const string &oldNodeIdentifier, const string &newNodeIdentifier)
287 {
288 NodeReplacement n;
289 n.compositionIdentifier = compositionIdentifier;
290 n.oldNodeIdentifier = oldNodeIdentifier;
291 n.newNodeIdentifier = newNodeIdentifier;
292 return nodeReplacements.find(n) != nodeReplacements.end();
293 };
294
295 // Add nodes that have the same identifier but different node classes to `nodeReplacements` (if not already there).
296
297 for (map<string, pair<VuoNode *, VuoNode *> >::iterator i = oldAndNewNodeForIdentifier.begin(); i != oldAndNewNodeForIdentifier.end(); ++i)
298 if (i->second.first && i->second.second && i->second.first->getNodeClass() != i->second.second->getNodeClass() &&
299 ! nodeReplacementExists(compositionIdentifier, i->first, i->first))
300 addNodeReplacement(compositionIdentifier, i->first, i->first);
301
302 // Add nodes whose node classes are being replaced to `nodeReplacements` (if not already there).
303
304 for (map<string, pair<VuoNode *, VuoNode *> >::iterator i = oldAndNewNodeForIdentifier.begin(); i != oldAndNewNodeForIdentifier.end(); ++i)
305 {
306 if (i->second.first && i->second.second)
307 {
308 string nodeClassName = i->second.second->getNodeClass()->getClassName();
309 for (const NodeClassReplacement &nodeClassReplacement : nodeClassReplacements)
310 {
311 if (nodeClassReplacement.nodeClassName == nodeClassName && ! nodeReplacementExists(compositionIdentifier, i->first, i->first))
312 {
313 addNodeReplacement(compositionIdentifier, i->first, i->first, nodeClassReplacement.oldAndNewPortNames);
314 break;
315 }
316 }
317 }
318 }
319
320 // Recursively diff nodes that are subcompositions.
321
322 for (map<string, pair<VuoNode *, VuoNode *> >::iterator i = oldAndNewNodeForIdentifier.begin(); i != oldAndNewNodeForIdentifier.end(); ++i)
323 {
324 string nodeIdentifier;
325
326 VuoCompilerComposition *newSubcomposition = NULL;
327 if (i->second.second)
328 {
329 VuoCompilerNodeClass *newNodeClass = i->second.second->getNodeClass()->getCompiler();
330 if (newNodeClass->isSubcomposition())
331 {
332 string newGraphvizDeclaration = newNodeClass->getSourceCode();
333 newSubcomposition = VuoCompilerComposition::newCompositionFromGraphvizDeclaration(newGraphvizDeclaration, compiler);
334
335 nodeIdentifier = i->second.second->getCompiler()->getIdentifier();
336 }
337 }
338
339 VuoCompilerComposition *oldSubcomposition = NULL;
340 if (i->second.first)
341 {
342 string nodeClassName = i->second.first->getNodeClass()->getClassName();
343
344 set<NodeClassReplacement>::iterator replacementIter;
345 for (replacementIter = nodeClassReplacements.begin(); replacementIter != nodeClassReplacements.end(); ++replacementIter)
346 if (replacementIter->nodeClassName == nodeClassName)
347 break;
348
349 if (replacementIter != nodeClassReplacements.end())
350 {
351 if (! replacementIter->oldSubcompositionSourceCode.empty())
352 {
353 oldSubcomposition = VuoCompilerComposition::newCompositionFromGraphvizDeclaration(replacementIter->oldSubcompositionSourceCode, compiler);
354
355 nodeIdentifier = i->second.first->getCompiler()->getIdentifier();
356 }
357 }
358 else
359 oldSubcomposition = newSubcomposition;
360 }
361
362 if (oldSubcomposition || newSubcomposition)
363 diff(oldSubcomposition, newSubcomposition, compositionIdentifier, compositionPath, nodeIdentifier, compiler, diffJson);
364
365 if (oldSubcomposition != newSubcomposition)
366 delete oldSubcomposition;
367
368 delete newSubcomposition;
369 }
370
371 // Diff nodes that are being replaced / replacing another.
372 // For nodes that are subcompositions, this uses the port mappings added to `replacements` during the recursive calls.
373
374 for (set<NodeReplacement>::iterator nodeReplacementIter = nodeReplacements.begin(); nodeReplacementIter != nodeReplacements.end(); ++nodeReplacementIter)
375 {
376 if (nodeReplacementIter->compositionIdentifier == compositionIdentifier)
377 {
378 // { "replace" : "<composition path>/<node identifier>", "with" : "<composition path>/<node identifier>",
379 // "ports" : [
380 // { "map" : "<port identifier>", "to" : "<port identifier>" },
381 // { "map" : "<port identifier>", "to" : "<port identifier>" },
382 // ... ] }
383
384 map<string, VuoNode *>::iterator oldNodeIter = oldNodeForIdentifier.find(nodeReplacementIter->oldNodeIdentifier);
385 if (oldNodeIter == oldNodeForIdentifier.end())
386 continue;
387 map<string, VuoNode *>::iterator newNodeIter = newNodeForIdentifier.find(nodeReplacementIter->newNodeIdentifier);
388 if (newNodeIter == newNodeForIdentifier.end())
389 continue;
390
391 json_object *replaceObj = json_object_new_object();
392 json_object *oldNodePath = json_object_new_string((compositionPath + "/" + nodeReplacementIter->oldNodeIdentifier).c_str());
393 json_object_object_add(replaceObj, "replace", oldNodePath);
394 json_object *newNodePath = json_object_new_string((compositionPath + "/" + nodeReplacementIter->newNodeIdentifier).c_str());
395 json_object_object_add(replaceObj, "with", newNodePath);
396 json_object *ports = json_object_new_array();
397
398 map<string, string> oldAndNewPortNames = nodeReplacementIter->oldAndNewPortNames;
399
400 if (nodeReplacementIter->shouldMapIdenticalPortNames)
401 {
402 vector<VuoPort *> oldInputPorts = oldNodeIter->second->getInputPorts();
403 vector<VuoPort *> oldOutputPorts = oldNodeIter->second->getOutputPorts();
404 vector<VuoPort *> newInputPorts = newNodeIter->second->getInputPorts();
405 vector<VuoPort *> newOutputPorts = newNodeIter->second->getOutputPorts();
406 for (vector<VuoPort *>::iterator oldPortIter = oldInputPorts.begin(); oldPortIter != oldInputPorts.end(); ++oldPortIter)
407 {
408 for (vector<VuoPort *>::iterator newPortIter = newInputPorts.begin(); newPortIter != newInputPorts.end(); ++newPortIter)
409 {
410 if (VuoCompilerComposition::portsMatch(*oldPortIter, *newPortIter))
411 {
412 string oldPortName = (*oldPortIter)->getClass()->getName();
413 string newPortName = (*newPortIter)->getClass()->getName();
414 oldAndNewPortNames[oldPortName] = newPortName;
415 break;
416 }
417 }
418 }
419 for (vector<VuoPort *>::iterator oldPortIter = oldOutputPorts.begin(); oldPortIter != oldOutputPorts.end(); ++oldPortIter)
420 {
421 for (vector<VuoPort *>::iterator newPortIter = newOutputPorts.begin(); newPortIter != newOutputPorts.end(); ++newPortIter)
422 {
423 if (VuoCompilerComposition::portsMatch(*oldPortIter, *newPortIter))
424 {
425 string oldPortName = (*oldPortIter)->getClass()->getName();
426 string newPortName = (*newPortIter)->getClass()->getName();
427 oldAndNewPortNames[oldPortName] = newPortName;
428 break;
429 }
430 }
431 }
432 }
433
434 for (map<string, string>::const_iterator portMapIter = oldAndNewPortNames.begin(); portMapIter != oldAndNewPortNames.end(); ++portMapIter)
435 {
436 json_object *portObj = json_object_new_object();
437 json_object *oldPortName = json_object_new_string(portMapIter->first.c_str());
438 json_object_object_add(portObj, "map", oldPortName);
439 json_object *newPortName = json_object_new_string(portMapIter->second.c_str());
440 json_object_object_add(portObj, "to", newPortName);
441 json_object_array_add(ports, portObj);
442 }
443
444 json_object_object_add(replaceObj, "ports", ports);
445 json_object_array_add(diffJson, replaceObj);
446 }
447 }
448
449 // Diff published ports.
450
451 bool publishedPortsChanged[2] = { false, false };
452 vector<VuoPublishedPort *> oldPublishedPorts[2];
453 vector<VuoPublishedPort *> newPublishedPorts[2];
454 string nodeIdentifier[2];
455 map<string, string> oldAndNewPublishedPortNames[2];
456
457 for (int i = 0; i < 2; ++i)
458 {
459 if (i == 0)
460 {
461 if (oldComposition)
462 oldPublishedPorts[i] = oldComposition->getBase()->getPublishedInputPorts();
463 if (newComposition)
464 newPublishedPorts[i] = newComposition->getBase()->getPublishedInputPorts();
465 nodeIdentifier[i] = "PublishedInputs";
466 }
467 else
468 {
469 if (oldComposition)
470 oldPublishedPorts[i] = oldComposition->getBase()->getPublishedOutputPorts();
471 if (newComposition)
472 newPublishedPorts[i] = newComposition->getBase()->getPublishedOutputPorts();
473 nodeIdentifier[i] = "PublishedOutputs";
474 }
475
476 for (size_t j = 0; j < oldPublishedPorts[i].size() && j < newPublishedPorts[i].size(); ++j)
477 {
478 VuoPublishedPort *oldPort = oldPublishedPorts[i][j];
479 VuoPublishedPort *newPort = newPublishedPorts[i][j];
480
481 if (VuoCompilerComposition::portsMatch(oldPort, newPort))
482 {
483 string oldPortName = oldPort->getClass()->getName();
484 string newPortName = newPort->getClass()->getName();
485 oldAndNewPublishedPortNames[i][oldPortName] = newPortName;
486 }
487 else
488 publishedPortsChanged[i] = true;
489 }
490
491 if (oldPublishedPorts[i].size() != newPublishedPorts[i].size())
492 publishedPortsChanged[i] = true;
493 }
494
495 if (publishedPortsChanged[0] || publishedPortsChanged[1])
496 {
497 bool addBoth = oldPublishedPorts[0].empty() && oldPublishedPorts[1].empty();
498 bool removeBoth = newPublishedPorts[0].empty() && newPublishedPorts[1].empty();
499
500 for (int i = 0; i < 2; ++i)
501 {
502 if (removeBoth)
503 {
504 // { "remove" : "<composition path>/PublishedInputs" }
505 json_object *remove = json_object_new_object();
506 json_object *nodePath = json_object_new_string((compositionPath + "/" + nodeIdentifier[i]).c_str());
507 json_object_object_add(remove, "remove", nodePath);
508 json_object_array_add(diffJson, remove);
509
510 if (i == 0)
511 {
512 json_object *remove = json_object_new_object();
513 json_object *nodePath = json_object_new_string((compositionPath + "/" + "PublishedInputsTrigger").c_str());
514 json_object_object_add(remove, "remove", nodePath);
515 json_object_array_add(diffJson, remove);
516 }
517 }
518 else if (addBoth)
519 {
520 // { "add" : "<composition path>/PublishedInputs" }
521 json_object *add = json_object_new_object();
522 json_object *nodePath = json_object_new_string((compositionPath + "/" + nodeIdentifier[i]).c_str());
523 json_object_object_add(add, "add", nodePath);
524 json_object_array_add(diffJson, add);
525
526 if (i == 0)
527 {
528 json_object *add = json_object_new_object();
529 json_object *nodePath = json_object_new_string((compositionPath + "/" + "PublishedInputsTrigger").c_str());
530 json_object_object_add(add, "add", nodePath);
531 json_object_array_add(diffJson, add);
532 }
533 }
534 else if (publishedPortsChanged[i])
535 {
536 // { "replace" : "<composition path>/PublishedInputs", "with" : "<composition path>/PublishedInputs",
537 // "ports" : [
538 // { "map" : "<published port name>", "to" : "<published port name>" },
539 // { "map" : "<published port name>", "to" : "<published port name>" },
540 // ... ] }
541 json_object *replaceObj = json_object_new_object();
542 json_object *nodePath = json_object_new_string((compositionPath + "/" + nodeIdentifier[i]).c_str());
543 json_object_get(nodePath);
544 json_object_object_add(replaceObj, "replace", nodePath);
545 json_object_object_add(replaceObj, "with", nodePath);
546 json_object *ports = json_object_new_array();
547 for (map<string, string>::iterator j = oldAndNewPublishedPortNames[i].begin(); j != oldAndNewPublishedPortNames[i].end(); ++j)
548 {
549 json_object *portObj = json_object_new_object();
550 json_object *oldPublishedPortName = json_object_new_string(j->first.c_str());
551 json_object_object_add(portObj, "map", oldPublishedPortName);
552 json_object *newPublishedPortName = json_object_new_string(j->second.c_str());
553 json_object_object_add(portObj, "to", newPublishedPortName);
554 json_object_array_add(ports, portObj);
555 }
556 json_object_object_add(replaceObj, "ports", ports);
557 json_object_array_add(diffJson, replaceObj);
558 }
559 }
560 }
561
562 if (! parentCompositionIdentifier.empty())
563 {
564 for (set<NodeReplacement>::iterator i = nodeReplacements.begin(); i != nodeReplacements.end(); ++i)
565 {
566 if (i->compositionIdentifier == parentCompositionIdentifier &&
567 i->oldNodeIdentifier == unqualifiedCompositionIdentifier && i->newNodeIdentifier == unqualifiedCompositionIdentifier)
568 {
569 NodeReplacement n = *i;
570
571 for (int j = 0; j < 2; ++j)
572 n.oldAndNewPortNames.insert(oldAndNewPublishedPortNames[j].begin(), oldAndNewPublishedPortNames[j].end());
573
574 n.shouldMapIdenticalPortNames = false;
575
576 nodeReplacements.erase(i);
577 nodeReplacements.insert(n);
578 break;
579 }
580 }
581 }
582}
583
587bool operator<(const VuoCompilerCompositionDiff::NodeReplacement &lhs, const VuoCompilerCompositionDiff::NodeReplacement &rhs)
588{
589 return (lhs.compositionIdentifier != rhs.compositionIdentifier ?
590 lhs.compositionIdentifier < rhs.compositionIdentifier :
591 (lhs.oldNodeIdentifier != rhs.oldNodeIdentifier ?
592 lhs.oldNodeIdentifier < rhs.oldNodeIdentifier :
593 lhs.newNodeIdentifier < rhs.newNodeIdentifier));
594}
595
599bool operator<(const VuoCompilerCompositionDiff::NodeClassReplacement &lhs, const VuoCompilerCompositionDiff::NodeClassReplacement &rhs)
600{
601 return (lhs.nodeClassName < rhs.nodeClassName);
602}
603
607bool operator<(const VuoCompilerCompositionDiff::Refactoring &lhs, const VuoCompilerCompositionDiff::Refactoring &rhs)
608{
609 return (lhs.compositionIdentifier != rhs.compositionIdentifier ?
610 lhs.compositionIdentifier < rhs.compositionIdentifier :
611 lhs.unqualifiedSubcompositionIdentifier < rhs.unqualifiedSubcompositionIdentifier);
612}
613
618void VuoCompilerCompositionDiff::addNodeReplacementInTopLevelComposition(const string &oldNodeIdentifier, const string &newNodeIdentifier)
619{
621}
622
626void VuoCompilerCompositionDiff::addNodeReplacementInTopLevelComposition(const string &oldNodeIdentifier, const string &newNodeIdentifier,
627 const map<string, string> &oldAndNewPortNames)
628{
629 addNodeReplacement(VuoCompilerComposition::topLevelCompositionIdentifier, oldNodeIdentifier, newNodeIdentifier, oldAndNewPortNames);
630}
631
636void VuoCompilerCompositionDiff::addNodeReplacement(const string &compositionIdentifier, const string &oldNodeIdentifier, const string &newNodeIdentifier)
637{
638 NodeReplacement n;
639 n.compositionIdentifier = compositionIdentifier;
640 n.oldNodeIdentifier = oldNodeIdentifier;
641 n.newNodeIdentifier = newNodeIdentifier;
642 n.shouldMapIdenticalPortNames = true;
643 nodeReplacements.insert(n);
644}
645
649void VuoCompilerCompositionDiff::addNodeReplacement(const string &compositionIdentifier, const string &oldNodeIdentifier, const string &newNodeIdentifier,
650 const map<string, string> &oldAndNewPortNames)
651{
652 NodeReplacement n;
653 n.compositionIdentifier = compositionIdentifier;
654 n.oldNodeIdentifier = oldNodeIdentifier;
655 n.newNodeIdentifier = newNodeIdentifier;
656 n.oldAndNewPortNames = oldAndNewPortNames;
657 n.shouldMapIdenticalPortNames = false;
658 nodeReplacements.insert(n);
659}
660
667{
668 NodeClassReplacement n;
669 n.nodeClassName = oldNodeClass->getBase()->getClassName();
670
671 auto makeOldAndNewPortNames = [&n] (const vector<VuoPortClass *> &oldPortClasses, const vector<VuoPortClass *> &newPortClasses)
672 {
673 for (VuoPortClass *oldPortClass : oldPortClasses)
674 {
675 for (VuoPortClass *newPortClass : newPortClasses)
676 {
677 if (VuoCompilerComposition::portClassesMatch(oldPortClass, newPortClass))
678 {
679 n.oldAndNewPortNames[oldPortClass->getName()] = newPortClass->getName();
680 break;
681 }
682 }
683 }
684 };
685 vector<VuoPortClass *> oldInputPorts = oldNodeClass->getBase()->getInputPortClasses();
686 vector<VuoPortClass *> oldOutputPorts = oldNodeClass->getBase()->getOutputPortClasses();
687 vector<VuoPortClass *> newInputPorts = newNodeClass->getBase()->getInputPortClasses();
688 vector<VuoPortClass *> newOutputPorts = newNodeClass->getBase()->getOutputPortClasses();
689 makeOldAndNewPortNames(oldInputPorts, newInputPorts);
690 makeOldAndNewPortNames(oldOutputPorts, newOutputPorts);
691
692 if (oldNodeClass->isSubcomposition())
693 n.oldSubcompositionSourceCode = oldNodeClass->getSourceCode();
694
695 nodeClassReplacements.insert(n);
696}
697
702{
703 moduleReplacements.insert(moduleKey);
704}
705
713void VuoCompilerCompositionDiff::addRefactoring(const string &compositionIdentifier, const set<VuoCompilerNode *> &nodesMoved, VuoCompilerNode *subcompositionMovedTo)
714{
715 Refactoring r;
716
717 r.compositionIdentifier = compositionIdentifier;
718 r.unqualifiedSubcompositionIdentifier = subcompositionMovedTo->getIdentifier();
719
720 for (VuoCompilerNode *node : nodesMoved)
721 r.nodeIdentifiers.insert(node->getIdentifier());
722
723 refactorings.insert(r);
724}
725
730{
731 set<string> moduleKeys;
732
733 for (const NodeClassReplacement &ncr : nodeClassReplacements)
734 moduleKeys.insert(ncr.nodeClassName);
735
736 for (const string &moduleKey : moduleReplacements)
737 moduleKeys.insert(moduleKey);
738
739 return moduleKeys;
740}
741
745bool VuoCompilerCompositionDiff::isNodeBeingReplaced(const string &compositionIdentifier, const string &oldNodeIdentifier) const
746{
747 for (set<NodeReplacement>::const_iterator i = nodeReplacements.begin(); i != nodeReplacements.end(); ++i)
748 if ((*i).compositionIdentifier == compositionIdentifier && (*i).oldNodeIdentifier == oldNodeIdentifier)
749 return true;
750
751 return false;
752}
753
757bool VuoCompilerCompositionDiff::isNodeReplacingAnother(const string &compositionIdentifier, const string &newNodeIdentifier) const
758{
759 for (set<NodeReplacement>::const_iterator i = nodeReplacements.begin(); i != nodeReplacements.end(); ++i)
760 if ((*i).compositionIdentifier == compositionIdentifier && (*i).newNodeIdentifier == newNodeIdentifier)
761 return true;
762
763 return false;
764}
765
769bool VuoCompilerCompositionDiff::isNodeBeingRefactored(const string &parentCompositionIdentifier, const string &compositionIdentifier, const string &nodeIdentifier) const
770{
771 for (const Refactoring &r : refactorings)
772 if ((r.compositionIdentifier == compositionIdentifier && r.nodeIdentifiers.find(nodeIdentifier) != r.nodeIdentifiers.end()) ||
773 (r.compositionIdentifier == parentCompositionIdentifier && r.unqualifiedSubcompositionIdentifier == compositionIdentifier && r.nodeIdentifiers.find(nodeIdentifier) != r.nodeIdentifiers.end()))
774 return true;
775
776 return false;
777}