int Submodel::replaceElement(SBase* toReplace, SBase* replacement) { if (mInstantiatedModel == NULL) return LIBSBML_INVALID_OBJECT; //Must call 'instantiate' first (and probably rename your objects, too!). string oldSId = toReplace->getId(); string oldMetaId = toReplace->getMetaId(); List* allElements = mInstantiatedModel->getAllElements(); for (ListIterator iter = allElements->begin(); iter != allElements->end(); ++iter) { SBase* element = static_cast<SBase*>(*iter); assert(element != NULL); if (element == NULL) continue; if (toReplace->isSetId()) { if (replacement->getTypeCode() == SBML_UNIT_DEFINITION) { element->renameUnitSIdRefs(toReplace->getId(), replacement->getId()); } else { element->renameSIdRefs(toReplace->getId(), replacement->getId()); } } if (toReplace->isSetMetaId()) { element->renameMetaIdRefs(toReplace->getMetaId(), replacement->getMetaId()); } } delete allElements; return LIBSBML_OPERATION_FAILED; }
/** @cond doxygenLibsbmlInternal */ void CompModelPlugin::renameIDs(List* allElements, const string& prefix) { if (prefix=="") return; //Nothing to prepend. vector<pair<string, string> > renamedSIds; vector<pair<string, string> > renamedUnitSIds; vector<pair<string, string> > renamedMetaIds; //PrefixTransformer trans(prefix); for (unsigned long el=0; el < allElements->getSize(); ++el) { SBase* element = static_cast<SBase*>(allElements->get(el)); string id = element->getId(); string metaid = element->getMetaId(); //element->transformIdentifiers(&trans); element->prependStringToAllIdentifiers(prefix); if (element->getTypeCode() == SBML_LOCAL_PARAMETER) { element->setId(id); //Change it back. This would perhaps be better served by overriding 'prependStringToAllIdentifiers' but hey. } string newid = element->getId(); string newmetaid = element->getMetaId(); if (id != newid) { int type = element->getTypeCode(); if (type==SBML_UNIT_DEFINITION) { renamedUnitSIds.push_back(make_pair(id, newid)); } else if (type==SBML_COMP_PORT) { //Do nothing--these can only be referenced from outside the Model, so they need to be handled specially. // (In the default case, we throw them away). } else { //This is a little dangerous, but hey! What's a little danger between friends! //(What we are assuming is that any attribute you can get with 'getId' is of the type 'SId') renamedSIds.push_back(make_pair(id, newid)); } } if (metaid != newmetaid) { renamedMetaIds.push_back(make_pair(metaid, newmetaid)); } } for (unsigned long el=0; el<allElements->getSize(); el++) { SBase* element = static_cast<SBase*>(allElements->get(el)); for (size_t id=0; id<renamedSIds.size(); id++) { element->renameSIdRefs(renamedSIds[id].first, renamedSIds[id].second); } for (size_t uid=0; uid<renamedUnitSIds.size(); uid++) { element->renameUnitSIdRefs(renamedUnitSIds[uid].first, renamedUnitSIds[uid].second); } for (size_t mid=0; mid<renamedMetaIds.size(); mid++) { element->renameMetaIdRefs(renamedMetaIds[mid].first, renamedMetaIds[mid].second); } } }
/** @cond doxygenLibsbmlInternal */ int Replacing::updateIDs(SBase* oldnames, SBase* newnames) { int ret = LIBSBML_OPERATION_SUCCESS; SBMLDocument* doc = getSBMLDocument(); if (oldnames->isSetId() && !newnames->isSetId()) { if (doc) { string error = "Unable to transform IDs in Replacing::updateIDs during replacement: the '" + oldnames->getId() + "' element's replacement does not have an ID set."; doc->getErrorLog()->logPackageError("comp", CompMustReplaceIDs, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn()); } return LIBSBML_INVALID_OBJECT; } if (oldnames->isSetMetaId() && !newnames->isSetMetaId()) { if (doc) { string error = "Unable to transform IDs in Replacing::updateIDs during replacement: the replacement of the element with metaid '" + oldnames->getMetaId() + "' does not have a metaid."; doc->getErrorLog()->logPackageError("comp", CompMustReplaceMetaIDs, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn()); } return LIBSBML_INVALID_OBJECT; } //LS DEBUG Somehow we need to check identifiers from other packages here (like spatial id's). How, exactly, is anyone's guess. Model* replacedmod = const_cast<Model*>(CompBase::getParentModel(oldnames)); KineticLaw* replacedkl; ASTNode newkl; if (replacedmod==NULL) { if (doc) { string error = "Unable to transform IDs in Replacing::updateIDs during replacement: the replacement of '" + oldnames->getId() + "' does not have a valid model."; doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn()); } return LIBSBML_INVALID_OBJECT; } List* allElements = replacedmod->getAllElements(); string oldid = oldnames->getId(); string newid = newnames->getId(); if (!oldid.empty()) { switch(oldnames->getTypeCode()) { case SBML_UNIT_DEFINITION: replacedmod->renameUnitSIdRefs(oldid, newid); for (unsigned int e=0; e<allElements->getSize(); e++) { SBase* element = static_cast<SBase*>(allElements->get(e)); element->renameUnitSIdRefs(oldid, newid); } break; case SBML_LOCAL_PARAMETER: replacedkl = static_cast<KineticLaw*>(oldnames->getAncestorOfType(SBML_KINETIC_LAW)); if (replacedkl->isSetMath()) { newkl = *replacedkl->getMath(); newkl.renameSIdRefs(oldid, newid); replacedkl->setMath(&newkl); } break; case SBML_COMP_PORT: break; //LS DEBUG And here is where we would need some sort of way to check if the id wasn't an SId for some objects. default: replacedmod->renameSIdRefs(oldnames->getId(), newnames->getId()); for (unsigned int e=0; e<allElements->getSize(); e++) { SBase* element = static_cast<SBase*>(allElements->get(e)); element->renameSIdRefs(oldid, newid); } } } string oldmetaid = oldnames->getMetaId(); string newmetaid = newnames->getMetaId(); if (oldnames->isSetMetaId()) { replacedmod->renameMetaIdRefs(oldmetaid, newmetaid); for (unsigned int e=0; e<allElements->getSize(); e++) { SBase* element = static_cast<SBase*>(allElements->get(e)); element->renameMetaIdRefs(oldmetaid, newmetaid); } } //LS DEBUG And here is where we would need some sort of way to check for ids that were not 'id' or 'metaid'. delete allElements; return ret; }
int SBMLIdConverter::convert() { if (mDocument == NULL) return LIBSBML_INVALID_OBJECT; Model* mModel = mDocument->getModel(); if (mModel == NULL) return LIBSBML_INVALID_OBJECT; // nothing to do if (!mProps->hasOption("currentIds") || !mProps->hasOption("newIds")) return LIBSBML_OPERATION_SUCCESS; bool success = true; IdList currentIds(mProps->getOption("currentIds")->getValue()); IdList newIds(mProps->getOption("newIds")->getValue()); // if the size does not match something is wrong. if (newIds.size() != currentIds.size()) return LIBSBML_UNEXPECTED_ATTRIBUTE; List* allElements = mDocument->getAllElements(); std::map<std::string, std::string> renamed; // rename ids for (unsigned int i = 0; i < allElements->getSize(); ++i) { SBase* current = static_cast<SBase*>(allElements->get(i)); if (current == NULL || !current->isSetId() || current->getTypeCode() == SBML_LOCAL_PARAMETER) continue; for (unsigned int j = 0; j < currentIds.size(); ++j) { if (current->getId() != currentIds.at((int)j)) continue; // return error code in case new id is invalid if (!SyntaxChecker::isValidSBMLSId(newIds.at((int)j))) { delete allElements; return LIBSBML_INVALID_ATTRIBUTE_VALUE; } current->setId(newIds.at((int)j)); renamed[currentIds.at((int)j)] = newIds.at((int)j); break; } } // update all references that we changed std::map<std::string, std::string>::const_iterator it; for (unsigned int i = 0; i < allElements->getSize(); ++i) { SBase* current = static_cast<SBase*>(allElements->get(i)); for (it = renamed.begin(); it != renamed.end(); ++it) { current->renameSIdRefs(it->first, it->second); } } delete allElements; if (success) return LIBSBML_OPERATION_SUCCESS; return LIBSBML_OPERATION_FAILED; }