120 delete oldComposition;
122 string diffString = json_object_to_json_string_ext(diffJson, JSON_C_TO_STRING_PLAIN);
124 json_object_put(diffJson);
132 const string &parentCompositionIdentifier,
const string &parentCompositionPath,
133 const string &unqualifiedCompositionIdentifier,
136 string compositionIdentifier = (parentCompositionIdentifier.empty() ?
137 unqualifiedCompositionIdentifier :
138 parentCompositionIdentifier +
"/" + unqualifiedCompositionIdentifier);
139 string compositionPath = (parentCompositionPath.empty() ?
140 unqualifiedCompositionIdentifier :
141 parentCompositionPath +
"/" + unqualifiedCompositionIdentifier);
145 set<VuoNode *> oldNodes;
146 set<VuoNode *> newNodes;
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)
157 string identifier = (*i)->getCompiler()->getGraphvizIdentifier();
158 oldNodeForIdentifier[identifier] = *i;
159 oldAndNewNodeForIdentifier[identifier].first = *i;
161 for (set<VuoNode *>::iterator i = newNodes.begin(); i != newNodes.end(); ++i)
163 string identifier = (*i)->getCompiler()->getGraphvizIdentifier();
164 newNodeForIdentifier[identifier] = *i;
165 oldAndNewNodeForIdentifier[identifier].second = *i;
168 for (map<string, VuoNode *>::iterator oldNodeIter = oldNodeForIdentifier.begin(); oldNodeIter != oldNodeForIdentifier.end(); ++oldNodeIter)
170 if (newNodeForIdentifier.find(oldNodeIter->first) == newNodeForIdentifier.end() &&
171 ! isNodeBeingReplaced(compositionIdentifier, oldNodeIter->first) &&
172 ! isNodeBeingRefactored(parentCompositionIdentifier, unqualifiedCompositionIdentifier, oldNodeIter->first))
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);
181 for (map<string, VuoNode *>::iterator newNodeIter = newNodeForIdentifier.begin(); newNodeIter != newNodeForIdentifier.end(); ++newNodeIter)
183 if (oldNodeForIdentifier.find(newNodeIter->first) == oldNodeForIdentifier.end() &&
184 ! isNodeReplacingAnother(compositionIdentifier, newNodeIter->first) &&
185 ! isNodeBeingRefactored(parentCompositionIdentifier, unqualifiedCompositionIdentifier, newNodeIter->first))
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);
197 if (! oldComposition)
201 json_object_object_add(
add,
"add", nodePath);
202 json_object_array_add(diffJson,
add);
204 if (! newComposition)
208 json_object_object_add(remove,
"remove", nodePath);
209 json_object_array_add(diffJson, remove);
214 auto buildMovePath = [](
const Refactoring &r,
const string &nodeIdentifier)
216 return r.compositionIdentifier +
"/" + nodeIdentifier;
218 auto buildToPath = [](
const Refactoring &r,
const string &nodeIdentifier)
220 return r.compositionIdentifier +
"/" + r.unqualifiedSubcompositionIdentifier +
"/" + nodeIdentifier;
223 for (
const Refactoring &r : refactorings)
225 if (compositionIdentifier == r.compositionIdentifier)
227 for (
const string &nodeIdentifier : r.nodeIdentifiers)
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);
238 else if (parentCompositionIdentifier == r.compositionIdentifier && unqualifiedCompositionIdentifier == r.unqualifiedSubcompositionIdentifier)
240 for (
const string &nodeIdentifier : r.nodeIdentifiers)
248 int length = json_object_array_length(diffJson);
249 for (
int i = 0; i < length; ++i)
251 json_object *curr = json_object_array_get_idx(diffJson, i);
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))
265 for (
VuoPort *internalPort : newNodeForIdentifier[nodeIdentifier]->getInputPorts())
267 for (
VuoCable *cable : internalPort->getConnectedCables())
269 if (cable->isPublished() && cable->getCompiler()->carriesData())
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);
281 json_object_object_add(move,
"ports", ports);
286 auto nodeReplacementExists = [
this](
const string &compositionIdentifier,
const string &oldNodeIdentifier,
const string &newNodeIdentifier)
289 n.compositionIdentifier = compositionIdentifier;
290 n.oldNodeIdentifier = oldNodeIdentifier;
291 n.newNodeIdentifier = newNodeIdentifier;
292 return nodeReplacements.find(n) != nodeReplacements.end();
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))
304 for (map<
string, pair<VuoNode *, VuoNode *> >::iterator i = oldAndNewNodeForIdentifier.begin(); i != oldAndNewNodeForIdentifier.end(); ++i)
306 if (i->second.first && i->second.second)
308 string nodeClassName = i->second.second->getNodeClass()->getClassName();
309 for (
const NodeClassReplacement &nodeClassReplacement : nodeClassReplacements)
311 if (nodeClassReplacement.nodeClassName == nodeClassName && ! nodeReplacementExists(compositionIdentifier, i->first, i->first))
313 addNodeReplacement(compositionIdentifier, i->first, i->first, nodeClassReplacement.oldAndNewPortNames);
322 for (map<
string, pair<VuoNode *, VuoNode *> >::iterator i = oldAndNewNodeForIdentifier.begin(); i != oldAndNewNodeForIdentifier.end(); ++i)
324 string nodeIdentifier;
327 if (i->second.second)
332 string newGraphvizDeclaration = newNodeClass->
getSourceCode();
335 nodeIdentifier = i->second.second->getCompiler()->getIdentifier();
342 string nodeClassName = i->second.first->getNodeClass()->getClassName();
344 set<NodeClassReplacement>::iterator replacementIter;
345 for (replacementIter = nodeClassReplacements.begin(); replacementIter != nodeClassReplacements.end(); ++replacementIter)
346 if (replacementIter->nodeClassName == nodeClassName)
349 if (replacementIter != nodeClassReplacements.end())
351 if (! replacementIter->oldSubcompositionSourceCode.empty())
355 nodeIdentifier = i->second.first->getCompiler()->getIdentifier();
359 oldSubcomposition = newSubcomposition;
362 if (oldSubcomposition || newSubcomposition)
363 diff(oldSubcomposition, newSubcomposition, compositionIdentifier, compositionPath, nodeIdentifier, compiler, diffJson);
365 if (oldSubcomposition != newSubcomposition)
366 delete oldSubcomposition;
368 delete newSubcomposition;
374 for (set<NodeReplacement>::iterator nodeReplacementIter = nodeReplacements.begin(); nodeReplacementIter != nodeReplacements.end(); ++nodeReplacementIter)
376 if (nodeReplacementIter->compositionIdentifier == compositionIdentifier)
384 map<string, VuoNode *>::iterator oldNodeIter = oldNodeForIdentifier.find(nodeReplacementIter->oldNodeIdentifier);
385 if (oldNodeIter == oldNodeForIdentifier.end())
387 map<string, VuoNode *>::iterator newNodeIter = newNodeForIdentifier.find(nodeReplacementIter->newNodeIdentifier);
388 if (newNodeIter == newNodeForIdentifier.end())
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);
398 map<string, string> oldAndNewPortNames = nodeReplacementIter->oldAndNewPortNames;
400 if (nodeReplacementIter->shouldMapIdenticalPortNames)
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)
408 for (vector<VuoPort *>::iterator newPortIter = newInputPorts.begin(); newPortIter != newInputPorts.end(); ++newPortIter)
412 string oldPortName = (*oldPortIter)->getClass()->getName();
413 string newPortName = (*newPortIter)->getClass()->getName();
414 oldAndNewPortNames[oldPortName] = newPortName;
419 for (vector<VuoPort *>::iterator oldPortIter = oldOutputPorts.begin(); oldPortIter != oldOutputPorts.end(); ++oldPortIter)
421 for (vector<VuoPort *>::iterator newPortIter = newOutputPorts.begin(); newPortIter != newOutputPorts.end(); ++newPortIter)
425 string oldPortName = (*oldPortIter)->getClass()->getName();
426 string newPortName = (*newPortIter)->getClass()->getName();
427 oldAndNewPortNames[oldPortName] = newPortName;
434 for (map<string, string>::const_iterator portMapIter = oldAndNewPortNames.begin(); portMapIter != oldAndNewPortNames.end(); ++portMapIter)
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);
444 json_object_object_add(replaceObj,
"ports", ports);
445 json_object_array_add(diffJson, replaceObj);
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];
457 for (
int i = 0; i < 2; ++i)
465 nodeIdentifier[i] =
"PublishedInputs";
473 nodeIdentifier[i] =
"PublishedOutputs";
476 for (
size_t j = 0; j < oldPublishedPorts[i].size() && j < newPublishedPorts[i].size(); ++j)
485 oldAndNewPublishedPortNames[i][oldPortName] = newPortName;
488 publishedPortsChanged[i] =
true;
491 if (oldPublishedPorts[i].size() != newPublishedPorts[i].size())
492 publishedPortsChanged[i] =
true;
495 if (publishedPortsChanged[0] || publishedPortsChanged[1])
497 bool addBoth = oldPublishedPorts[0].empty() && oldPublishedPorts[1].empty();
498 bool removeBoth = newPublishedPorts[0].empty() && newPublishedPorts[1].empty();
500 for (
int i = 0; i < 2; ++i)
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);
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);
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);
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);
534 else if (publishedPortsChanged[i])
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);
547 for (map<string, string>::iterator j = oldAndNewPublishedPortNames[i].begin(); j != oldAndNewPublishedPortNames[i].end(); ++j)
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);
556 json_object_object_add(replaceObj,
"ports", ports);
557 json_object_array_add(diffJson, replaceObj);
562 if (! parentCompositionIdentifier.empty())
564 for (set<NodeReplacement>::iterator i = nodeReplacements.begin(); i != nodeReplacements.end(); ++i)
566 if (i->compositionIdentifier == parentCompositionIdentifier &&
567 i->oldNodeIdentifier == unqualifiedCompositionIdentifier && i->newNodeIdentifier == unqualifiedCompositionIdentifier)
569 NodeReplacement n = *i;
571 for (
int j = 0; j < 2; ++j)
572 n.oldAndNewPortNames.insert(oldAndNewPublishedPortNames[j].begin(), oldAndNewPublishedPortNames[j].end());
574 n.shouldMapIdenticalPortNames =
false;
576 nodeReplacements.erase(i);
577 nodeReplacements.insert(n);
587 bool operator<(
const VuoCompilerCompositionDiff::NodeReplacement &lhs,
const VuoCompilerCompositionDiff::NodeReplacement &rhs)
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));
599 bool operator<(
const VuoCompilerCompositionDiff::NodeClassReplacement &lhs,
const VuoCompilerCompositionDiff::NodeClassReplacement &rhs)
601 return (lhs.nodeClassName < rhs.nodeClassName);
607 bool operator<(
const VuoCompilerCompositionDiff::Refactoring &lhs,
const VuoCompilerCompositionDiff::Refactoring &rhs)
609 return (lhs.compositionIdentifier != rhs.compositionIdentifier ?
610 lhs.compositionIdentifier < rhs.compositionIdentifier :
611 lhs.unqualifiedSubcompositionIdentifier < rhs.unqualifiedSubcompositionIdentifier);
618 void VuoCompilerCompositionDiff::addNodeReplacementInTopLevelComposition(
const string &oldNodeIdentifier,
const string &newNodeIdentifier)
626 void VuoCompilerCompositionDiff::addNodeReplacementInTopLevelComposition(
const string &oldNodeIdentifier,
const string &newNodeIdentifier,
627 const map<string, string> &oldAndNewPortNames)
639 n.compositionIdentifier = compositionIdentifier;
640 n.oldNodeIdentifier = oldNodeIdentifier;
641 n.newNodeIdentifier = newNodeIdentifier;
642 n.shouldMapIdenticalPortNames =
true;
643 nodeReplacements.insert(n);
650 const map<string, string> &oldAndNewPortNames)
653 n.compositionIdentifier = compositionIdentifier;
654 n.oldNodeIdentifier = oldNodeIdentifier;
655 n.newNodeIdentifier = newNodeIdentifier;
656 n.oldAndNewPortNames = oldAndNewPortNames;
657 n.shouldMapIdenticalPortNames =
false;
658 nodeReplacements.insert(n);
668 NodeClassReplacement n;
671 auto makeOldAndNewPortNames = [&n] (
const vector<VuoPortClass *> &oldPortClasses,
const vector<VuoPortClass *> &newPortClasses)
679 n.oldAndNewPortNames[oldPortClass->getName()] = newPortClass->getName();
689 makeOldAndNewPortNames(oldInputPorts, newInputPorts);
690 makeOldAndNewPortNames(oldOutputPorts, newOutputPorts);
693 n.oldSubcompositionSourceCode = oldNodeClass->
getSourceCode();
695 nodeClassReplacements.insert(n);
703 moduleReplacements.insert(moduleKey);
717 r.compositionIdentifier = compositionIdentifier;
718 r.unqualifiedSubcompositionIdentifier = subcompositionMovedTo->
getIdentifier();
721 r.nodeIdentifiers.insert(node->getIdentifier());
723 refactorings.insert(r);
731 set<string> moduleKeys;
733 for (
const NodeClassReplacement &ncr : nodeClassReplacements)
734 moduleKeys.insert(ncr.nodeClassName);
736 for (
const string &moduleKey : moduleReplacements)
737 moduleKeys.insert(moduleKey);
745 bool VuoCompilerCompositionDiff::isNodeBeingReplaced(
const string &compositionIdentifier,
const string &oldNodeIdentifier)
const
747 for (set<NodeReplacement>::const_iterator i = nodeReplacements.begin(); i != nodeReplacements.end(); ++i)
748 if ((*i).compositionIdentifier == compositionIdentifier && (*i).oldNodeIdentifier == oldNodeIdentifier)
757 bool VuoCompilerCompositionDiff::isNodeReplacingAnother(
const string &compositionIdentifier,
const string &newNodeIdentifier)
const
759 for (set<NodeReplacement>::const_iterator i = nodeReplacements.begin(); i != nodeReplacements.end(); ++i)
760 if ((*i).compositionIdentifier == compositionIdentifier && (*i).newNodeIdentifier == newNodeIdentifier)
769 bool VuoCompilerCompositionDiff::isNodeBeingRefactored(
const string &parentCompositionIdentifier,
const string &compositionIdentifier,
const string &nodeIdentifier)
const
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()))