/** @cond doxygenLibsbmlInternal */ int Replacing::replaceWithAndMaybeDelete(SBase* replacement, bool deleteme, ASTNode* conversionFactor) { //All of the following function calls that could result in errors set their own error messages. SBase* replaced = getReferencedElement(); if (replaced==NULL) return LIBSBML_INVALID_OBJECT; //Rename things int ret = updateIDs(replaced, replacement); if (ret != LIBSBML_OPERATION_SUCCESS) return ret; //Perform any conversions on references in the submodel. ret = performConversions(replacement, &conversionFactor); if (ret != LIBSBML_OPERATION_SUCCESS) return ret; //Finally, recurse down if there are things the replaced element itself replaced (or used to be replaced by) CompSBasePlugin* replacedplug = static_cast<CompSBasePlugin*>(replaced->getPlugin(getPrefix())); if (replacedplug==NULL) { //assert(false); //Not sure when this situation would come up, so I would like to see an example. //(sadly, I cannot set an assert in production code.) return LIBSBML_OPERATION_SUCCESS; //I guess? LS DEBUG } for (unsigned int re=0; re<replacedplug->getNumReplacedElements(); re++) { ret = replacedplug->getReplacedElement(re)->replaceWithAndMaybeDelete(replacement, true, conversionFactor); if (ret != LIBSBML_OPERATION_SUCCESS) return ret; } if (replacedplug->isSetReplacedBy()) { ret = replacedplug->getReplacedBy()->replaceWithAndMaybeDelete(replacement, deleteme, conversionFactor); if (ret != LIBSBML_OPERATION_SUCCESS) return ret; } return LIBSBML_OPERATION_SUCCESS; }
int SBaseRef::collectDeletions(set<SBase*>* removed, set<SBase*>* toremove) { SBase* todelete = getReferencedElement(); if (todelete==NULL) { return LIBSBML_INVALID_OBJECT; } if (removed) { if (removed->find(todelete) != removed->end()) { //Already deleted or replaced. return LIBSBML_OPERATION_SUCCESS; } } if (toremove) { toremove->insert(todelete); } CompSBasePlugin* todplug = static_cast<CompSBasePlugin*>(todelete->getPlugin(getPrefix())); if (todplug != NULL) { for (unsigned long re=0; re<todplug->getNumReplacedElements(); re++) { todplug->getReplacedElement(re)->collectDeletions(removed, toremove); } if (todplug->isSetReplacedBy()) { todplug->getReplacedBy()->collectDeletions(removed, toremove); } } return LIBSBML_OPERATION_SUCCESS; }
int ReplacedElement::performReplacementAndCollect(set<SBase*>* removed, set<SBase*>* toremove) { SBMLDocument* doc = getSBMLDocument(); if (isSetDeletion()) { //Deletions don't need to be replaced. return LIBSBML_OPERATION_SUCCESS; } //Find the various objects and plugin objects we need for this to work. SBase* lore = getParentSBMLObject(); ListOf* lorelist = static_cast<ListOf*>(lore); if (lore == NULL) { if (doc) { string error = "Cannot carry out replacement in ReplacedElement::performReplacement: no parent <listOfReplacedElements> could be found for the given replacement element."; doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn()); } return LIBSBML_INVALID_OBJECT; } if (lore->getTypeCode() != SBML_LIST_OF || lorelist->getItemTypeCode() != SBML_COMP_REPLACEDELEMENT) { if (doc) { string error = "Cannot carry out replacement in ReplacedElement::performReplacement: no parent <listOfReplacedElements> could be found for the given replacement element."; doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn()); } return LIBSBML_INVALID_OBJECT; } SBase* parent = lore->getParentSBMLObject(); if (parent==NULL) { if (doc) { string error = "Cannot carry out replacement in ReplacedElement::performReplacement: no parent could be found for the parent <listOfReplacedElements> object."; doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn()); } return LIBSBML_INVALID_OBJECT; } SBase* ref = getReferencedElement(); if (ref==NULL) { //getReferencedElement sets its own error messages. return LIBSBML_INVALID_OBJECT; } if (removed && removed->find(ref)!=removed->end()) { //Already deleted: can't get the deleted element's ID to if (doc) { string error = "Cannot carry out replacement in ReplacedElement::performReplacement: a <" + parent->getElementName() + ">"; if (parent->isSetId()) { error += " with the ID '" + parent->getId() + "'"; } error += " has a child <replacedElement> that points to something that has already been deleted, probably because its parent was deleted."; doc->getErrorLog()->logPackageError("comp", CompDeletedReplacement, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn()); } return LIBSBML_INVALID_OBJECT; } //Update the IDs. int ret = updateIDs(ref, parent); if (ret != LIBSBML_OPERATION_SUCCESS) { return ret; } //Perform any conversions on references in the submodel. ASTNode* blank = NULL; ret = performConversions(parent, &blank); if (ret != LIBSBML_OPERATION_SUCCESS) { if (blank != NULL) { delete blank; } return ret; } CompSBasePlugin* refplug = static_cast<CompSBasePlugin*>(ref->getPlugin(getPrefix())); if (refplug != NULL) { //Now recurse down the 'replace*' tree, renaming IDs and deleting things as we go. for (unsigned int re=0; re<refplug->getNumReplacedElements(); re++) { refplug->getReplacedElement(re)->replaceWithAndMaybeDelete(parent, true, blank); if (toremove) { toremove->insert(refplug->getReplacedElement(re)->getReferencedElement()); } } if (refplug->isSetReplacedBy()) { //Even if the subelement used to be replaced by something further down, it is now being replaced by the parent. It just can't catch a break, it seems. refplug->getReplacedBy()->replaceWithAndMaybeDelete(parent, true, blank); if (toremove) { toremove->insert(refplug->getReplacedBy()->getReferencedElement()); } } } if (toremove) { toremove->insert(ref); } if (blank != NULL) { delete blank; } return LIBSBML_OPERATION_SUCCESS; }