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);
    }
  }
}
Exemple #3
0
/** @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;
}
void
Model::dealWithModelUnits()
{
  UnitRefsFilter filter;
  List * elements = getAllElements(&filter);
  unsigned int n = 0;
  unsigned int num = elements->getSize();
  
  if (isSetVolumeUnits())
  {
    std::string volume = getVolumeUnits();
    // if in an L3 model a user used volume as an id of a UnitDefinition
    // but they declared the volume units of teh model to be something 
    // else then the UD with id volume is nothing to do with the 
    // L2 interpretation of volume
    // so replace that UD and all references to it 
    if (volume != "volume")
    {
      UnitDefinition * existingUD = removeUnitDefinition("volume");
      if (existingUD != NULL)
      {
        std::string newSubsName = "volumeFromOriginal";
        existingUD->setId(newSubsName);
        SBase* obj;
        for (n = 0; n < num; n++)
        {
          obj = (SBase*)(elements->get(n));
          obj->renameUnitSIdRefs("volume", newSubsName);
        }
        addUnitDefinition(existingUD);
      }
    }
    UnitDefinition * ud = getUnitDefinition(volume) != NULL ? 
                          getUnitDefinition(volume)->clone() : NULL;
    if (ud != NULL)
    {
      ud->setId("volume");
    }
    else
    {
      Unit *u = new Unit(getSBMLNamespaces());
      u->initDefaults();
      u->setKind(UnitKind_forName(volume.c_str()));
      ud = new UnitDefinition(getSBMLNamespaces());
      ud->setId("volume");
      ud->addUnit(u);
    }
    addUnitDefinition(ud);
  }
  if (isSetAreaUnits())
  {
    std::string area = getAreaUnits();
    // if in an L3 model a user used area as an id of a UnitDefinition
    // but they declared the area units of teh model to be something 
    // else then the UD with id area is nothing to do with the 
    // L2 interpretation of area
    // so replace that UD and all references to it 
    if (area != "area")
    {
      UnitDefinition * existingUD = removeUnitDefinition("area");
      if (existingUD != NULL)
      {
        std::string newSubsName = "areaFromOriginal";
        existingUD->setId(newSubsName);
        SBase* obj;
        for (n = 0; n < num; n++)
        {
          obj = (SBase*)(elements->get(n));
          obj->renameUnitSIdRefs("area", newSubsName);
        }
        addUnitDefinition(existingUD);
      }
    }
    UnitDefinition * ud = getUnitDefinition(area) != NULL ? 
                          getUnitDefinition(area)->clone() : NULL;
    if (ud != NULL)
    {
      ud->setId("area");
    }
    else
    {
      Unit *u = new Unit(getSBMLNamespaces());
      u->initDefaults();
      u->setKind(UnitKind_forName(area.c_str()));
      ud = new UnitDefinition(getSBMLNamespaces());
      ud->setId("area");
      ud->addUnit(u);
    }
    addUnitDefinition(ud);
  }
  if (isSetLengthUnits())
  {
    std::string length = getLengthUnits();
    // if in an L3 model a user used length as an id of a UnitDefinition
    // but they declared the length units of teh model to be something 
    // else then the UD with id length is nothing to do with the 
    // L2 interpretation of length
    // so replace that UD and all references to it 
    if (length != "length")
    {
      UnitDefinition * existingUD = removeUnitDefinition("length");
      if (existingUD != NULL)
      {
        std::string newSubsName = "lengthFromOriginal";
        existingUD->setId(newSubsName);
        SBase* obj;
        for (n = 0; n < num; n++)
        {
          obj = (SBase*)(elements->get(n));
          obj->renameUnitSIdRefs("length", newSubsName);
        }
        addUnitDefinition(existingUD);
      }
    }
    UnitDefinition * ud = getUnitDefinition(length) != NULL ? 
                          getUnitDefinition(length)->clone() : NULL;
    if (ud != NULL)
    {
      ud->setId("length");
    }
    else
    {
      Unit *u = new Unit(getSBMLNamespaces());
      u->initDefaults();
      u->setKind(UnitKind_forName(length.c_str()));
      ud = new UnitDefinition(getSBMLNamespaces());
      ud->setId("length");
      ud->addUnit(u);
    }
    addUnitDefinition(ud);
  }
  if (isSetSubstanceUnits())
  {
    std::string substance = getSubstanceUnits();
    // if in an L3 model a user used substance as an id of a UnitDefinition
    // but they declared the substance units of teh model to be something 
    // else then the UD with id substance is nothing to do with the 
    // L2 interpretation of substance
    // so replace that UD and all references to it 
    if (substance != "substance")
    {
      UnitDefinition * existingUD = removeUnitDefinition("substance");
      if (existingUD != NULL)
      {
        std::string newSubsName = "substanceFromOriginal";
        existingUD->setId(newSubsName);
        SBase* obj;
        for (n = 0; n < num; n++)
        {
          obj = (SBase*)(elements->get(n));
          obj->renameUnitSIdRefs("substance", newSubsName);
        }
        addUnitDefinition(existingUD);
      }
    }
    UnitDefinition * ud = getUnitDefinition(substance) != NULL ? 
                          getUnitDefinition(substance)->clone() : NULL;
    if (ud != NULL)
    {
      ud->setId("substance");
    }
    else
    {
      Unit *u = new Unit(getSBMLNamespaces());
      u->initDefaults();
      u->setKind(UnitKind_forName(substance.c_str()));
      ud = new UnitDefinition(getSBMLNamespaces());
      ud->setId("substance");
      ud->addUnit(u);
    }
    addUnitDefinition(ud);
  }
  if (isSetTimeUnits())
  {
    std::string time = getTimeUnits();
    // if in an L3 model a user used time as an id of a UnitDefinition
    // but they declared the time units of teh model to be something 
    // else then the UD with id time is nothing to do with the 
    // L2 interpretation of time
    // so replace that UD and all references to it 
    if (time != "time")
    {
      UnitDefinition * existingUD = removeUnitDefinition("time");
      if (existingUD != NULL)
      {
        std::string newSubsName = "timeFromOriginal";
        existingUD->setId(newSubsName);
        SBase* obj;
        for (n = 0; n < num; n++)
        {
          obj = (SBase*)(elements->get(n));
          obj->renameUnitSIdRefs("time", newSubsName);
        }
        addUnitDefinition(existingUD);
      }
    }
    UnitDefinition * ud = getUnitDefinition(time) != NULL ? 
                          getUnitDefinition(time)->clone() : NULL;
    if (ud != NULL)
    {
      ud->setId("time");
    }
    else
    {
      ud = new UnitDefinition(getSBMLNamespaces());
      ud->setId("time");
      Unit *u = ud->createUnit();
      u->initDefaults();
      u->setKind(UnitKind_forName(time.c_str()));
    }
    addUnitDefinition(ud);
  }
}