void 
PackageIdReplacementCheck::checkReferencedElement(ReplacedElement& repE)
{
  // if the deletion attribute is set then it does not point
  // to another package element
  if (repE.isSetDeletion() == true)
  {
    return;
  }

  unsigned int numErrsB4 = repE.getSBMLDocument()->getNumErrors();
  
  SBase* refElem = repE.getReferencedElement();
  
  // if there is an issue with references the getReferencedElement
  // will log errors and possibly fail
  // we dont want to try any further
  unsigned int numErrsAfter = repE.getSBMLDocument()->getNumErrors();

  if (numErrsB4 != numErrsAfter || refElem == NULL)
  {
    return;
  }

  SBase * parent = repE.getParentSBMLObject()->getParentSBMLObject();

  if (refElem->isSetId() == true && parent->isSetId() == false)
  {
    logMissingIdAttribute(repE, refElem, parent);
  }


}
void 
PackageIdReplacementCheck::checkReferencedElement(ReplacedBy& repBy)
{
  unsigned int numErrsB4 = repBy.getSBMLDocument()->getNumErrors();
  
  SBase* refElem = repBy.getReferencedElement();
  
  // if there is an issue with references the getReferencedElement
  // will log errors and possibly fail
  // we dont want to try any further
  unsigned int numErrsAfter = repBy.getSBMLDocument()->getNumErrors();

  if (numErrsB4 != numErrsAfter || refElem == NULL)
  {
    return;
  }

  SBase * parent = repBy.getParentSBMLObject();

  if (parent->isSetId() == true && refElem->isSetId() == false)
  {
    logMissingIdAttribute(repBy, refElem, parent);
  }

}
/*
 * @return the error message to use when logging constraint violations.
 * This method is called by logFailure.
 *
 * Returns a message that the given @p id and its corresponding object are
 * in  conflict with an object previously defined.
 */
const string
NumericArgsMathCheck::getMessage (const ASTNode& node, const SBase& object)
{

  ostringstream msg;

  //msg << getPreamble();

  char * formula = SBML_formulaToString(&node);
  msg << "The formula '" << formula;
  msg << "' in the " << getFieldname() << " element of the <" << object.getElementName();
  msg << "> ";
  switch(object.getTypeCode()) {
  case SBML_INITIAL_ASSIGNMENT:
  case SBML_EVENT_ASSIGNMENT:
  case SBML_ASSIGNMENT_RULE:
  case SBML_RATE_RULE:
    //LS DEBUG:  could use other attribute values, or 'isSetActualId'.
    break;
  default:
    if (object.isSetId()) {
      msg << "with id '" << object.getId() << "' ";
    }
    break;
  }
  msg << "uses an argument to a operator that expects a numeric value.";
  safe_free(formula);

  return msg.str();
}
/*
* Logs a message about the conditional part of a piecewise function 
* that should have dimensionless units
*/
void 
ArgumentsUnitsCheck::logInconsistentPiecewiseCondition (const ASTNode & node, 
                                          const SBase & sb)
{
  char * formula = SBML_formulaToString(&node);
  msg = "The formula '";
  msg += formula;
  msg += "' in the math element of the <";
  msg += sb.getElementName();
  msg += "> ";
  switch(sb.getTypeCode()) {
  case SBML_INITIAL_ASSIGNMENT:
  case SBML_EVENT_ASSIGNMENT:
  case SBML_ASSIGNMENT_RULE:
  case SBML_RATE_RULE:
    //LS DEBUG:  could use other attribute values, or 'isSetActualId'.
    break;
  default:
    if (sb.isSetId()) {
      msg += "with id '";
      msg += sb.getId() + "' ";
    }
    break;
  }
  msg += "uses a piecewise function";
  msg += " where the conditional statement is not dimensionless.";
  safe_free(formula);

  logFailure(sb, msg);

}
/*
 * @return the error message to use when logging constraint violations.
 * This method is called by logFailure.
 *
 * Returns a message that the given @p id and its corresponding object are
 * in  conflict with an object previously defined.
 */
const string
PieceBooleanMathCheck::getMessage (const ASTNode& node, const SBase& object)
{

  ostringstream oss_msg;

  //oss_msg << getPreamble();

  char * formula = SBML_formulaToString(&node);
  oss_msg << "The formula '" << formula;
  oss_msg << "' in the " << getFieldname() << " element of the <" << object.getElementName();
  oss_msg << "> ";
  switch(object.getTypeCode()) {
  case SBML_INITIAL_ASSIGNMENT:
  case SBML_EVENT_ASSIGNMENT:
  case SBML_ASSIGNMENT_RULE:
  case SBML_RATE_RULE:
    //LS DEBUG:  could use other attribute values, or 'isSetActualId'.
    break;
  default:
    if (object.isSetId()) {
      oss_msg << "with id '" << object.getId() << "' ";
    }
    break;
  }
  oss_msg << "uses a piecewise function that does not return a Boolean.";
  safe_free(formula);

  return oss_msg.str();
}
/*
 * @return the error message to use when logging constraint violations.
 * This method is called by logFailure.
 *
 * Returns a message that the given @p id and its corresponding object are
 * in  conflict with an object previously defined.
 */
const string
FunctionApplyMathCheck::getMessage (const ASTNode& node, const SBase& object)
{

  ostringstream msg;

  //msg << getPreamble();
  char * formula = SBML_formulaToString(&node);
  msg << "The formula '" << formula;
  msg << "' in the " << getFieldname() << " element of the <" << object.getElementName();
  msg << "> ";
  switch(object.getTypeCode()) {
  case SBML_INITIAL_ASSIGNMENT:
  case SBML_EVENT_ASSIGNMENT:
  case SBML_ASSIGNMENT_RULE:
  case SBML_RATE_RULE:
    //LS DEBUG:  could use other attribute values, or 'isSetActualId'.
    break;
  default:
    if (object.isSetId()) {
      msg << "with id '" << object.getId() << "' ";
    }
    break;
  }
  msg << "uses '" << node.getName() << "' which is not a function definition id.";
  safe_free(formula);

  return msg.str();
}
Ejemplo n.º 7
0
/*
 * Subclasses should override this method to read values from the given
 * XMLAttributes set into their specific fields.  Be sure to call your
 * parents implementation of this method as well.
 */
void
SpeciesReference::readL3Attributes (const XMLAttributes& attributes)
{
  const unsigned int level = 3;
  const unsigned int version = getVersion();
  //
  // stoichiometry: double   { use="optional" default="1" }  (L2v1->)
  //
  mIsSetStoichiometry = attributes.readInto("stoichiometry", mStoichiometry, getErrorLog(), false, getLine(), getColumn());

  string elplusid = "<" + getElementName() + ">";
  if (!mId.empty()) {
    elplusid += " with the id '" + mId + "'";
  }
  SBase* rxn = getAncestorOfType(SBML_REACTION);
  if (rxn && rxn->isSetId()) 
  {
    elplusid += " from the <reaction> with the id '" + rxn->getId() + "'";
  }
  //
  // constant: bool { use="required" } (L3v1 -> )
  //
  mIsSetConstant = attributes.readInto("constant", mConstant, getErrorLog(), false, getLine(), getColumn());
  if (!mIsSetConstant && !isModifier())
  {
    logError(AllowedAttributesOnSpeciesReference, level, version, 
             "The required attribute 'constant' is missing from the "
             + elplusid + ".");
  }

}
Ejemplo n.º 8
0
/*
 * @return the error message to use when logging constraint violations.
 * This method is called by logFailure.
 *
 * Returns a message that the given @p id and its corresponding object are
 * in  conflict with an object previously defined.
 */
const string
CiElementMathCheck::getMessage (const ASTNode& node, const SBase& object)
{

  ostringstream msg;

  //msg << getPreamble();
  char * formula = SBML_formulaToString(&node);
  msg << "The formula '" << formula;
  msg << "' in the " << getFieldname() << " element of the <" << object.getElementName();
  msg << "> ";
  switch(object.getTypeCode()) {
  case SBML_INITIAL_ASSIGNMENT:
  case SBML_EVENT_ASSIGNMENT:
  case SBML_ASSIGNMENT_RULE:
  case SBML_RATE_RULE:
    //LS DEBUG:  could use other attribute values, or 'isSetActualId'.
    break;
  default:
    if (object.isSetId()) {
      msg << "with id '" << object.getId() << "' ";
    }
    break;
  }
  if (object.getLevel() == 2 && object.getVersion() == 1)
    msg << "uses '" << node.getName() << "' that is not the id of a species/compartment/parameter.";
  else if (object.getLevel() < 3)
    msg << "uses '" << node.getName() << "' that is not the id of a species/compartment/parameter/reaction.";
  else
    msg << "uses '" << node.getName() << "' that is not the id of a species/compartment/parameter/reaction/speciesReference.";
  safe_free(formula);

  return msg.str();
}
/*
* Logs a message about a function that should return same units
* as the arguments
*/
void 
ArgumentsUnitsCheck::logInconsistentSameUnits (const ASTNode & node, 
                                             const SBase & sb)
{
  char * formula = SBML_formulaToString(&node);
  msg = "The formula '" ;
  msg += formula;
  msg += "' in the math element of the <";
  msg += sb.getElementName();
  msg += "> ";
  switch(sb.getTypeCode()) {
  case SBML_INITIAL_ASSIGNMENT:
  case SBML_EVENT_ASSIGNMENT:
  case SBML_ASSIGNMENT_RULE:
  case SBML_RATE_RULE:
    //LS DEBUG:  could use other attribute values, or 'isSetActualId'.
    break;
  default:
    if (sb.isSetId()) {
      msg += "with id '";
      msg += sb.getId() + "' ";
    }
    break;
  }
  msg += "can only act on variables with the same units.";
  safe_free(formula);

  logFailure(sb, msg);

}
Ejemplo n.º 10
0
/*
 * @return the error message to use when logging constraint violations.
 * This method is called by logFailure.
 *
 * Returns a message that the given @p id and its corresponding object are
 * in  conflict with an object previously defined.
 */
const string
ArgumentsUnitsCheck::getMessage (const ASTNode& node, const SBase& object)
{

  ostringstream msg;

  //msg << getPreamble();
  char * formula = SBML_formulaToString(&node);
  msg << "The formula '" << formula;
  msg << "' in the " << getFieldname() << " element of the <" << object.getElementName();
  msg << "> ";
  switch(object.getTypeCode()) {
  case SBML_INITIAL_ASSIGNMENT:
  case SBML_EVENT_ASSIGNMENT:
  case SBML_ASSIGNMENT_RULE:
  case SBML_RATE_RULE:
    //LS DEBUG:  could use other attribute values, or 'isSetActualId'.
    break;
  default:
    if (object.isSetId()) {
      msg << "with id '" << object.getId() << "' ";
    }
    break;
  }
  msg << "produces an exponent that is not an integer and thus may produce ";
  msg << "invalid units.";
  safe_free(formula);

  return msg.str();
}
Ejemplo n.º 11
0
/** @cond doxygenLibsbmlInternal */
void CompModelPlugin::findUniqueSubmodPrefixes(vector<string>& submodids, List* allElements)
{
  vector<int> suffixes(submodids.size(), 0);
  bool done=false;
  while (!done) {
    done = true;
    for (size_t str=0; str<submodids.size(); str++) {
      stringstream fullprefix;
      fullprefix << submodids[str];
      if (suffixes[str] > 0) {
        fullprefix << suffixes[str];
      }
      fullprefix << getDivider();
      for (unsigned long el=0; el<allElements->getSize(); ++el) {
        SBase* element = static_cast<SBase*>(allElements->get((unsigned int)el));
        if (element==NULL) {
          assert(false);
          continue;
        }
        if (element->isSetId() && element->getId().find(fullprefix.str())==0) {
          done = false;
          continue;
        }
        else if (element->isSetMetaId() && element->getMetaId().find(fullprefix.str())==0) {
          done = false;
          continue;
        }
        else if (element->hasNonstandardIdentifierBeginningWith(fullprefix.str())) {
          done = false;
          continue;
        }
        else {
          for (unsigned int p=0; p<element->getNumPlugins(); p++) {
            if (element->getPlugin(p)->hasIdentifierBeginningWith(fullprefix.str())) {
              done = false;
              continue;
            }
          }
        }
      }
      if (!done) {
        suffixes[str]++;
        continue; //Start over from the first ID; otherwise we end up checking a lot of things twice.
      }
    }
  }
  //Now change the submodid's:
  for (size_t str=0; str<submodids.size(); str++) {
    stringstream fullprefix;
    fullprefix << submodids[str];
    if (suffixes[str] > 0) {
      fullprefix << suffixes[str];
    }
    fullprefix << getDivider();
    submodids[str] = fullprefix.str();
  }
}
void
GroupsUniqueModelWideIds::logId (const SBase& object)
{ 
  if (object.isSetId())
  {
    const string& id = object.getId();

    mIdMap.insert( make_pair(id, &object) );
  }
}
/*
 * Checks that the id associated with the given object is unique.  If it
 * is not, logIdConflict is called.
 */
void
GroupsUniqueModelWideIds::doCheckId (const SBase& object)
{ 
  if (object.isSetId())
  {
    const string& id = object.getId();

    if (mIdMap.insert( make_pair(id, &object) ).second == false)
    {
      logIdConflict(id, object);
    }
  }
}
Ejemplo n.º 14
0
SBase*
ListOf::getElementBySId(const std::string& id)
{
  if (id.empty()) return NULL;
  for (unsigned int i = 0; i < size(); i++)
  {
    SBase* obj = get(i);
    if (obj->isSetId() && obj->getId() == id)
    {
      return obj;
    }
    obj = obj->getElementBySId(id);
    if (obj != NULL) return obj;
  }

  return getElementFromPluginsBySId(id);
}
Ejemplo n.º 15
0
/** @cond doxygenLibsbmlInternal */
void CompModelPlugin::resetPorts()
{
  for (unsigned int p=0; p<getNumPorts(); p++) {
    Port* port = getPort(p);
    SBase* referenced = port->getReferencedElement();
    if (port->isSetSBaseRef()) {
      port->unsetSBaseRef();
      port->unsetIdRef();
      port->unsetMetaIdRef();
      port->unsetUnitRef();
      int type = referenced->getTypeCode();
      if (referenced->isSetId() && 
          type != SBML_INITIAL_ASSIGNMENT &&
          type != SBML_ASSIGNMENT_RULE &&
          type != SBML_RATE_RULE &&
          type != SBML_EVENT_ASSIGNMENT) {
        if (type==SBML_UNIT_DEFINITION) {
          port->setUnitRef(referenced->getId());
        }
        else {
          port->setIdRef(referenced->getId());
        }
      }
      else if (referenced->isSetMetaId()) {
        port->setMetaIdRef(referenced->getMetaId());
      }
      else {
        stringstream newname;
        newname << "auto_port_" << p;
        referenced->setMetaId(newname.str());
        port->setMetaIdRef(newname.str());
      }
    }
    port->clearReferencedElement();
  }
}
Ejemplo n.º 16
0
int ReplacedBy::performReplacementAndCollect(set<SBase*>* removed, set<SBase*>* toremove)
{
  SBMLDocument* doc = getSBMLDocument();
  //Find the various objects and plugin objects we need for this to work.
  SBase* parent = getParentSBMLObject();
  if (parent==NULL) {
    if (doc) {
      string error = "Unable to perform replacement in ReplacedBy::performReplacement: no parent object for this <replacedBy> could be found.";
      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;
  }

  //Update the IDs. (Will set its own error messages.)
  int ret = updateIDs(ref, parent);
  
  //ReplacedBy elements do get the name of the top-level element, assuming it has one:
  if (parent->isSetId()) {
    ref->setId(parent->getId());
  }
  if (parent->isSetMetaId()) {
    ref->setMetaId(parent->getMetaId());
  }
  if (ret != LIBSBML_OPERATION_SUCCESS) return ret;

  //And finally, get ready to delete the parent object.
  if (toremove) {
    toremove->insert(parent);
  }
  return LIBSBML_OPERATION_SUCCESS;
}
Ejemplo n.º 17
0
SBase* 
SBaseRef::getReferencedElementFrom(Model* model)
{
  SBMLDocument* doc = getSBMLDocument();
  if (!hasRequiredAttributes()) {
    if (doc) {
      string error = "In SBaseRef::getReferencedElementFrom, unable to find referenced element from <" + getElementName() + "> ";
      if (isSetId()) {
        error += "with ID '" + getId() + "' ";
      }
      error += "as it does not have the required attributes.";
      int en = CompSBaseRefMustReferenceObject;
      switch(getTypeCode()) {
      case SBML_COMP_REPLACEDBY:
        en = CompReplacedByAllowedAttributes;
        break;
      case SBML_COMP_REPLACEDELEMENT:
        en = CompReplacedElementAllowedAttributes;
        break;
      case SBML_COMP_PORT:
        en = CompPortAllowedAttributes;
        break;
      case SBML_COMP_DELETION:
        en = CompDeletionAllowedAttributes;
      }
      doc->getErrorLog()->logPackageError("comp", en, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    }
    return NULL;
  }
  SBase* referent = NULL;
  if (isSetPortRef()) {
    CompModelPlugin* mplugin = static_cast<CompModelPlugin*>(model->getPlugin(getPrefix()));
    Port* port = mplugin->getPort(getPortRef());
    if (port==NULL) {
      if (doc) {
        string error = "In SBaseRef::getReferencedElementFrom, unable to find referenced element from SBase reference ";
        if (isSetId()) {
          error += "'" + getId() + "' ";
        }
        error += "as the port it references ('" + getPortRef() +"') could not be found.";
        doc->getErrorLog()->logPackageError("comp", CompPortRefMustReferencePort, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
      }
      return NULL;
    }
    mDirectReference = port;
    referent = port->getReferencedElementFrom(model);
  }
  else if (isSetIdRef()) {
    referent = model->getElementBySId(getIdRef());
    if (referent == NULL && doc) {
      string error = "In SBaseRef::getReferencedElementFrom, unable to find referenced element: no such SId in the model: '" + getIdRef() + "'.";
      if (doc->getErrorLog()->contains(UnrequiredPackagePresent) 
        || doc->getErrorLog()->contains(RequiredPackagePresent))
      {
        doc->getErrorLog()->logPackageError("comp", 
          CompIdRefMayReferenceUnknownPackage, getPackageVersion(), 
          getLevel(), getVersion(), error, getLine(), getColumn());
      }
      else
      {
        doc->getErrorLog()->logPackageError("comp", 
          CompIdRefMustReferenceObject, getPackageVersion(), 
          getLevel(), getVersion(), error, getLine(), getColumn());
      }
    }
  }
  else if (isSetUnitRef()) {
    referent = model->getUnitDefinition(getUnitRef());
    if (referent == NULL && doc) {
      string error = "In SBaseRef::getReferencedElementFrom, unable to find referenced element: no such Unit in the model: '" + getUnitRef() + "'.";
      doc->getErrorLog()->logPackageError("comp", CompUnitRefMustReferenceUnitDef, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    }
  }
  else if (isSetMetaIdRef()) {
    referent = model->getElementByMetaId(getMetaIdRef());
    if (referent == NULL && doc) {
      string error = "In SBaseRef::getReferencedElementFrom, unable to find referenced element: no such metaid in the model: '" + getMetaIdRef() + "'.";
      if (doc->getErrorLog()->contains(UnrequiredPackagePresent) 
        || doc->getErrorLog()->contains(RequiredPackagePresent))
      {
        doc->getErrorLog()->logPackageError("comp", 
          CompIdRefMayReferenceUnknownPackage, getPackageVersion(), 
          getLevel(), getVersion(), error, getLine(), getColumn());
      }
      else
      {
        doc->getErrorLog()->logPackageError("comp", 
          CompMetaIdRefMustReferenceObject, getPackageVersion(), 
          getLevel(), getVersion(), error, getLine(), getColumn());
      }
    }
  }
  else {
    //This is actually possible if the subclass overrides getNumReferents() (which some do).  In that case, we just return NULL and let the overriding function find the referent instead.
    return NULL;
  }
  if (referent == NULL) {
    //No need to set an error message--one was already set above.
    return NULL;
  }
  if (isSetSBaseRef()) {
    //We're drilling into the submodels here, so our referent must be a submodel.
    if (referent->getTypeCode() != SBML_COMP_SUBMODEL) {
      if (doc) {
        string error = "In SBaseRef::getReferencedElementFrom, unable to find referenced element: the element ";
        if (referent->isSetId()) {
          error += "'" + referent->getId() + "'";
        }
        else if (referent->isSetMetaId()) {
          error += "with the metaid '" + referent->getMetaId() + "'";
        }
        error += " is not a submodel, and therefore has no subobjects for the child <sBaseRef> to refer to.";
        doc->getErrorLog()->logPackageError("comp", CompParentOfSBRefChildMustBeSubmodel, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
      }
      return NULL;
    }
    Submodel* subm = static_cast<Submodel*>(referent);
    if (subm==NULL) {
      //Note:  should be impossible.
      if (doc) {
        string error = "In SBaseRef::getReferencedElementFrom, unable to find referenced element: the element ";
        if (referent->isSetId()) {
          error += "'" + referent->getId() + "' ";
        }
        else if (referent->isSetMetaId()) {
          error += "with the metaid '" + referent->getMetaId() + "' ";
        }
        error += "claims to be a Submodel, but could not be programmatically turned into one.";
        doc->getErrorLog()->logPackageError("comp", CompParentOfSBRefChildMustBeSubmodel, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
      }
      return NULL;
    }
    Model* inst = subm->getInstantiation();
    if (inst==NULL) {
      //No need to set an additional error, as 'getInstantiation' will set one itself.
      return NULL;
    }
    //Recursive, so will set its own error messages:
    referent = getSBaseRef()->getReferencedElementFrom(inst);
    mDirectReference = getSBaseRef()->getDirectReference();
  }
  return referent;
}
Ejemplo n.º 18
0
//static
void SBMLUtils::collectIds(Model* pModel, std::map<std::string, const SBase*>& ids, std::map<std::string, const SBase*>& metaIds)
{
  if (pModel != NULL)
    {
      // the model itself
      SBase* pSBase = NULL;
      std::string id;

      if (pModel->isSetId())
        {
          id = pModel->getId();

          if (ids.find(id) == ids.end())
            {
              ids.insert(std::pair<const std::string, const SBase*>(id, pModel));
            }
          else
            {
              CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
            }
        }

      if (pModel->isSetMetaId())
        {
          id = pModel->getMetaId();

          if (metaIds.find(id) == metaIds.end())
            {
              metaIds.insert(std::pair<const std::string, const SBase*>(id, pModel));
            }
          else
            {
              CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
            }
        }

      // ListOfFunctionDefinitions
      pSBase = pModel->getListOfFunctionDefinitions();

      if (pSBase != NULL)
        {
          if (pSBase->isSetId())
            {
              id = pSBase->getId();

              if (ids.find(id) == ids.end())
                {
                  ids.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                }
            }

          if (pSBase->isSetMetaId())
            {
              id = pSBase->getMetaId();

              if (metaIds.find(id) == metaIds.end())
                {
                  metaIds.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                }
            }

          // all FunctionDefinitions
          unsigned int i, iMax = pModel->getListOfFunctionDefinitions()->size();

          for (i = 0; i < iMax; ++i)
            {
              pSBase = pModel->getListOfFunctionDefinitions()->get(i);

              if (pSBase->isSetId())
                {
                  id = pSBase->getId();

                  if (ids.find(id) == ids.end())
                    {
                      ids.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                    }
                }

              if (pSBase->isSetMetaId())
                {
                  id = pSBase->getMetaId();

                  if (metaIds.find(id) == metaIds.end())
                    {
                      metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                    }
                }
            }
        }

      // ListOfUnitDefinition
      pSBase = pModel->getListOfUnitDefinitions();

      if (pSBase != NULL)
        {
          if (pSBase->isSetMetaId())
            {
              id = pSBase->getMetaId();

              if (metaIds.find(id) == metaIds.end())
                {
                  metaIds.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                }
            }

          // all UnitDefinitions
          // for each UnitDefinition: ListOfUnits, each Unit in ListOfUnits
          unsigned int i, iMax = pModel->getListOfUnitDefinitions()->size();

          for (i = 0; i < iMax; ++i)
            {
              /* UnitDefinitions have their ids in a different namespace
                 so we only consider meta ids.
                 */
              UnitDefinition* pUDef = pModel->getUnitDefinition(i);
              assert(pUDef != NULL);

              if (pUDef->isSetMetaId())
                {
                  id = pUDef->getMetaId();

                  if (metaIds.find(id) == metaIds.end())
                    {
                      metaIds.insert(std::pair<const std::string, const SBase*>(id, pUDef));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                    }
                }

              ListOf* pList = pUDef->getListOfUnits();

              if (pList != NULL)
                {
                  if (pList->isSetMetaId())
                    {
                      id = pList->getMetaId();

                      if (metaIds.find(id) == metaIds.end())
                        {
                          metaIds.insert(std::pair<const std::string, const SBase*>(id, pList));
                        }
                      else
                        {
                          CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                        }
                    }

                  unsigned j, jMax = pList->size();

                  for (j = 0; j < jMax; ++j)
                    {
                      pSBase = pList->get(j);
                      assert(pSBase != NULL);

                      if (pSBase->isSetMetaId())
                        {
                          id = pSBase->getMetaId();

                          if (metaIds.find(id) == metaIds.end())
                            {
                              metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                            }
                          else
                            {
                              CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                            }
                        }
                    }
                }
            }
        }

      // ListOfCompartmentTypes
      pSBase = pModel->getListOfCompartmentTypes();

      if (pSBase != NULL)
        {
          if (pSBase->isSetId())
            {
              id = pSBase->getId();

              if (ids.find(id) == ids.end())
                {
                  ids.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                }
            }

          if (pSBase->isSetMetaId())
            {
              id = pSBase->getMetaId();

              if (metaIds.find(id) == metaIds.end())
                {
                  metaIds.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                }
            }

          // each compartment type
          unsigned int i, iMax = pModel->getListOfCompartmentTypes()->size();

          for (i = 0; i < iMax; ++i)
            {
              pSBase = pModel->getCompartmentType(i);
              assert(pSBase != NULL);

              if (pSBase->isSetId())
                {
                  id = pSBase->getId();

                  if (ids.find(id) == ids.end())
                    {
                      ids.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                    }
                }

              if (pSBase->isSetMetaId())
                {
                  id = pSBase->getMetaId();

                  if (metaIds.find(id) == metaIds.end())
                    {
                      metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                    }
                }
            }
        }

      // ListOfSpeciesTypes
      pSBase = pModel->getListOfSpeciesTypes();

      if (pSBase != NULL)
        {
          if (pSBase->isSetId())
            {
              id = pSBase->getId();

              if (ids.find(id) == ids.end())
                {
                  ids.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                }
            }

          if (pSBase->isSetMetaId())
            {
              id = pSBase->getMetaId();

              if (metaIds.find(id) == metaIds.end())
                {
                  metaIds.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                }
            }

          // each species type
          unsigned int i, iMax = pModel->getListOfSpeciesTypes()->size();

          for (i = 0; i < iMax; ++i)
            {
              pSBase = pModel->getSpeciesType(i);
              assert(pSBase != NULL);

              if (pSBase->isSetId())
                {
                  id = pSBase->getId();

                  if (ids.find(id) == ids.end())
                    {
                      ids.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                    }
                }

              if (pSBase->isSetMetaId())
                {
                  id = pSBase->getMetaId();

                  if (metaIds.find(id) == metaIds.end())
                    {
                      metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                    }
                }
            }
        }

      // ListOfCompartments
      pSBase = pModel->getListOfCompartments();

      if (pSBase != NULL)
        {
          if (pSBase->isSetId())
            {
              id = pSBase->getId();

              if (ids.find(id) == ids.end())
                {
                  ids.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                }
            }

          if (pSBase->isSetMetaId())
            {
              id = pSBase->getMetaId();

              if (metaIds.find(id) == metaIds.end())
                {
                  metaIds.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                }
            }

          // all compartments
          unsigned int i, iMax = pModel->getListOfCompartments()->size();

          for (i = 0; i < iMax; ++i)
            {
              pSBase = pModel->getCompartment(i);
              assert(pSBase != NULL);

              if (pSBase->isSetId())
                {
                  id = pSBase->getId();

                  if (ids.find(id) == ids.end())
                    {
                      ids.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                    }
                }

              if (pSBase->isSetMetaId())
                {
                  id = pSBase->getMetaId();

                  if (metaIds.find(id) == metaIds.end())
                    {
                      metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                    }
                }
            }
        }

      // ListOfSpecies
      pSBase = pModel->getListOfSpecies();

      if (pSBase != NULL)
        {
          if (pSBase->isSetId())
            {
              id = pSBase->getId();

              if (ids.find(id) == ids.end())
                {
                  ids.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                }
            }

          if (pSBase->isSetMetaId())
            {
              id = pSBase->getMetaId();

              if (metaIds.find(id) == metaIds.end())
                {
                  metaIds.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                }
            }

          // all species
          unsigned int i, iMax = pModel->getListOfSpecies()->size();

          for (i = 0; i < iMax; ++i)
            {
              pSBase = pModel->getSpecies(i);
              assert(pSBase != NULL);

              if (pSBase->isSetId())
                {
                  id = pSBase->getId();

                  if (ids.find(id) == ids.end())
                    {
                      ids.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                    }
                }

              if (pSBase->isSetMetaId())
                {
                  id = pSBase->getMetaId();

                  if (metaIds.find(id) == metaIds.end())
                    {
                      metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                    }
                }
            }
        }

      // ListOfParameters
      pSBase = pModel->getListOfParameters();

      if (pSBase != NULL)
        {
          if (pSBase->isSetId())
            {
              id = pSBase->getId();

              if (ids.find(id) == ids.end())
                {
                  ids.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                }
            }

          if (pSBase->isSetMetaId())
            {
              id = pSBase->getMetaId();

              if (metaIds.find(id) == metaIds.end())
                {
                  metaIds.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                }
            }

          // each parameter
          unsigned int i, iMax = pModel->getListOfParameters()->size();

          for (i = 0; i < iMax; ++i)
            {
              pSBase = pModel->getParameter(i);
              assert(pSBase != NULL);

              if (pSBase->isSetId())
                {
                  id = pSBase->getId();

                  if (ids.find(id) == ids.end())
                    {
                      ids.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                    }
                }

              if (pSBase->isSetMetaId())
                {
                  id = pSBase->getMetaId();

                  if (metaIds.find(id) == metaIds.end())
                    {
                      metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                    }
                }
            }
        }

      // ListOfInitialAssignments
      pSBase = pModel->getListOfInitialAssignments();

      if (pSBase != NULL)
        {
          if (pSBase->isSetId())
            {
              id = pSBase->getId();

              if (ids.find(id) == ids.end())
                {
                  ids.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                }
            }

          if (pSBase->isSetMetaId())
            {
              id = pSBase->getMetaId();

              if (metaIds.find(id) == metaIds.end())
                {
                  metaIds.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                }
            }

          // each initial assignment
          unsigned int i, iMax = pModel->getListOfInitialAssignments()->size();

          for (i = 0; i < iMax; ++i)
            {
              pSBase = pModel->getInitialAssignment(i);
              assert(pSBase != NULL);

              // initial assignments have no ids
              if (pSBase->isSetMetaId())
                {
                  id = pSBase->getMetaId();

                  if (metaIds.find(id) == metaIds.end())
                    {
                      metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                    }
                }
            }
        }

      // ListOfRules
      pSBase = pModel->getListOfRules();

      if (pSBase != NULL)
        {
          if (pSBase->isSetId())
            {
              id = pSBase->getId();

              if (ids.find(id) == ids.end())
                {
                  ids.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                }
            }

          if (pSBase->isSetMetaId())
            {
              id = pSBase->getMetaId();

              if (metaIds.find(id) == metaIds.end())
                {
                  metaIds.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                }
            }

          // each rule
          unsigned int i, iMax = pModel->getListOfRules()->size();

          for (i = 0; i < iMax; ++i)
            {
              pSBase = pModel->getRule(i);
              assert(pSBase != NULL);

              // rules don't have ids
              if (pSBase->isSetMetaId())
                {
                  id = pSBase->getMetaId();

                  if (metaIds.find(id) == metaIds.end())
                    {
                      metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                    }
                }
            }
        }

      // ListOfConstraints
      pSBase = pModel->getListOfConstraints();

      if (pSBase != NULL)
        {
          if (pSBase->isSetId())
            {
              id = pSBase->getId();

              if (ids.find(id) == ids.end())
                {
                  ids.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                }
            }

          if (pSBase->isSetMetaId())
            {
              id = pSBase->getMetaId();

              if (metaIds.find(id) == metaIds.end())
                {
                  metaIds.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                }
            }

          // each constraint
          unsigned int i, iMax = pModel->getListOfConstraints()->size();

          for (i = 0; i < iMax; ++i)
            {
              pSBase = pModel->getConstraint(i);
              assert(pSBase != NULL);

              // constraints don't have ids
              if (pSBase->isSetMetaId())
                {
                  id = pSBase->getMetaId();

                  if (metaIds.find(id) == metaIds.end())
                    {
                      metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                    }
                }
            }
        }

      // ListOfReactions
      pSBase = pModel->getListOfReactions();

      if (pSBase != NULL)
        {
          if (pSBase->isSetId())
            {
              id = pSBase->getId();

              if (ids.find(id) == ids.end())
                {
                  ids.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                }
            }

          if (pSBase->isSetMetaId())
            {
              id = pSBase->getMetaId();

              if (metaIds.find(id) == metaIds.end())
                {
                  metaIds.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                }
            }

          // all reactions
          unsigned int i, iMax = pModel->getListOfReactions()->size();

          for (i = 0; i < iMax; ++i)
            {
              Reaction* pReaction = pModel->getReaction(i);
              assert(pReaction != NULL);

              if (pReaction->isSetId())
                {
                  id = pReaction->getId();

                  if (ids.find(id) == ids.end())
                    {
                      ids.insert(std::pair<const std::string, const SBase*>(id, pReaction));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                    }
                }

              if (pReaction->isSetMetaId())
                {
                  id = pReaction->getMetaId();

                  if (metaIds.find(id) == metaIds.end())
                    {
                      metaIds.insert(std::pair<const std::string, const SBase*>(id, pReaction));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                    }
                }

              // for each reaction: ListOfSubstrates, each substrate, ListOfProducts, each
              // Product, ListOfModifieres, each modifier, KineticLaw, ListOfparameters,
              // each parameter
              if (pReaction->getListOfReactants() != NULL)
                {
                  pSBase = pReaction->getListOfReactants();

                  if (pSBase->isSetMetaId())
                    {
                      id = pSBase->getMetaId();

                      if (metaIds.find(id) == metaIds.end())
                        {
                          metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                        }
                      else
                        {
                          CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                        }
                    }

                  unsigned int j, jMax = pReaction->getListOfReactants()->size();

                  for (j = 0; j < jMax; ++j)
                    {
                      pSBase = pReaction->getReactant(j);
                      assert(pSBase != NULL);

                      // since L2V2 species references can have ids
                      if (pSBase->isSetId())
                        {
                          id = pSBase->getId();

                          if (ids.find(id) == ids.end())
                            {
                              ids.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                            }
                          else
                            {
                              CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                            }
                        }

                      if (pSBase->isSetMetaId())
                        {
                          id = pSBase->getMetaId();

                          if (metaIds.find(id) == metaIds.end())
                            {
                              metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                            }
                          else
                            {
                              CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                            }
                        }
                    }
                }

              if (pReaction->getListOfProducts() != NULL)
                {
                  pSBase = pReaction->getListOfProducts();

                  if (pSBase->isSetMetaId())
                    {
                      id = pSBase->getMetaId();

                      if (metaIds.find(id) == metaIds.end())
                        {
                          metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                        }
                      else
                        {
                          CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                        }
                    }

                  unsigned int j, jMax = pReaction->getListOfProducts()->size();

                  for (j = 0; j < jMax; ++j)
                    {
                      pSBase = pReaction->getProduct(j);
                      assert(pSBase != NULL);

                      // since L2V2 species references can have ids
                      if (pSBase->isSetId())
                        {
                          id = pSBase->getId();

                          if (ids.find(id) == ids.end())
                            {
                              ids.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                            }
                          else
                            {
                              CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                            }
                        }

                      if (pSBase->isSetMetaId())
                        {
                          id = pSBase->getMetaId();

                          if (metaIds.find(id) == metaIds.end())
                            {
                              metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                            }
                          else
                            {
                              CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                            }
                        }
                    }
                }

              if (pReaction->getListOfModifiers() != NULL)
                {
                  pSBase = pReaction->getListOfModifiers();

                  if (pSBase->isSetMetaId())
                    {
                      id = pSBase->getMetaId();

                      if (metaIds.find(id) == metaIds.end())
                        {
                          metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                        }
                      else
                        {
                          CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                        }
                    }

                  unsigned int j, jMax = pReaction->getListOfModifiers()->size();

                  for (j = 0; j < jMax; ++j)
                    {
                      pSBase = pReaction->getModifier(j);
                      assert(pSBase != NULL);

                      // since L2V2 species references can have ids
                      if (pSBase->isSetId())
                        {
                          id = pSBase->getId();

                          if (ids.find(id) == ids.end())
                            {
                              ids.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                            }
                          else
                            {
                              CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                            }
                        }

                      if (pSBase->isSetMetaId())
                        {
                          id = pSBase->getMetaId();

                          if (metaIds.find(id) == metaIds.end())
                            {
                              metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                            }
                          else
                            {
                              CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                            }
                        }
                    }
                }

              KineticLaw* pKLaw = pReaction->getKineticLaw();

              if (pKLaw != NULL)
                {
                  if (pKLaw->isSetMetaId())
                    {
                      id = pKLaw->getMetaId();

                      if (metaIds.find(id) == metaIds.end())
                        {
                          metaIds.insert(std::pair<const std::string, const SBase*>(id, pKLaw));
                        }
                      else
                        {
                          CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                        }
                    }

                  pSBase = pKLaw->getListOfParameters();

                  if (pSBase != NULL)
                    {
                      if (pSBase->isSetMetaId())
                        {
                          id = pSBase->getMetaId();

                          if (metaIds.find(id) == metaIds.end())
                            {
                              metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                            }
                          else
                            {
                              CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                            }
                        }

                      unsigned int j, jMax = pKLaw->getListOfParameters()->size();

                      for (j = 0; j < jMax; ++j)
                        {
                          pSBase = pKLaw->getParameter(j);
                          assert(pSBase != NULL);

                          // local parameters have their ids in a
                          // different namespace
                          if (pSBase->isSetMetaId())
                            {
                              id = pSBase->getMetaId();

                              if (metaIds.find(id) == metaIds.end())
                                {
                                  metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                                }
                              else
                                {
                                  CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                                }
                            }
                        }
                    }
                }
            }
        }

      // ListOfEvents
      pSBase = pModel->getListOfEvents();

      if (pSBase != NULL)
        {
          if (pSBase->isSetId())
            {
              id = pSBase->getId();

              if (ids.find(id) == ids.end())
                {
                  ids.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                }
            }

          if (pSBase->isSetMetaId())
            {
              id = pSBase->getMetaId();

              if (metaIds.find(id) == metaIds.end())
                {
                  metaIds.insert(std::pair<const std::string, const SBase*>(id, pModel));
                }
              else
                {
                  CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                }
            }

          // each event
          unsigned int i, iMax = pModel->getListOfEvents()->size();

          for (i = 0; i < iMax; ++i)
            {
              Event* pEvent = pModel->getEvent(i);
              assert(pEvent != NULL);

              if (pEvent->isSetId())
                {
                  id = pEvent->getId();

                  if (ids.find(id) == ids.end())
                    {
                      ids.insert(std::pair<const std::string, const SBase*>(id, pEvent));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 68, id.c_str());
                    }
                }

              if (pEvent->isSetMetaId())
                {
                  id = pEvent->getMetaId();

                  if (metaIds.find(id) == metaIds.end())
                    {
                      metaIds.insert(std::pair<const std::string, const SBase*>(id, pEvent));
                    }
                  else
                    {
                      CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                    }
                }

              // in each event Trigger,Delay,ListOfEventAssignments, each event assignment
              if (pEvent->isSetTrigger())
                {
                  pSBase = pEvent->getTrigger();
                  assert(pSBase != NULL);

                  if (pSBase->isSetMetaId())
                    {
                      id = pSBase->getMetaId();

                      if (metaIds.find(id) == metaIds.end())
                        {
                          metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                        }
                      else
                        {
                          CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                        }
                    }
                }

              if (pEvent->isSetDelay())
                {
                  pSBase = pEvent->getDelay();
                  assert(pSBase != NULL);

                  if (pSBase->isSetMetaId())
                    {
                      id = pSBase->getMetaId();

                      if (metaIds.find(id) == metaIds.end())
                        {
                          metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                        }
                      else
                        {
                          CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                        }
                    }
                }

              if (pEvent->getListOfEventAssignments() != NULL)
                {
                  pSBase = pEvent->getListOfEventAssignments();

                  if (pSBase->isSetMetaId())
                    {
                      id = pSBase->getMetaId();

                      if (metaIds.find(id) == metaIds.end())
                        {
                          metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                        }
                      else
                        {
                          CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                        }
                    }

                  unsigned int j, jMax = pEvent->getListOfEventAssignments()->size();

                  for (j = 0; j < jMax; ++j)
                    {
                      pSBase = pEvent->getEventAssignment(j);
                      assert(pSBase != NULL);

                      if (pSBase->isSetMetaId())
                        {
                          id = pSBase->getMetaId();

                          if (metaIds.find(id) == metaIds.end())
                            {
                              metaIds.insert(std::pair<const std::string, const SBase*>(id, pSBase));
                            }
                          else
                            {
                              CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 67, id.c_str());
                            }
                        }
                    }
                }
            }
        }
    }
}
Ejemplo n.º 19
0
int CompModelPlugin::saveAllReferencedElements(set<SBase*> uniqueRefs, set<SBase*> replacedBys)
{
  SBMLDocument* doc = getSBMLDocument();
  Model* model = static_cast<Model*>(getParentSBMLObject());
  if (model==NULL) {
    if (doc) {
      string error = "Unable to discover any referenced elements in CompModelPlugin::saveAllReferencedElements: no Model parent of the 'comp' model plugin.";
      doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error);
    }
    return LIBSBML_OPERATION_FAILED;
  }
  int ret = LIBSBML_OPERATION_SUCCESS;

  //Get a list of everything, pull out anything that's a deletion, replacement, or port, and save what they're pointing to.
  //At the same time, make sure that no two things point to the same thing.
  set<SBase*> RE_deletions = set<SBase*>(); //Deletions only point to things in the same model.
  List* allElements = model->getAllElements();
  string modname = "the main model in the document";
  if (model->isSetId()) {
    modname = "the model '" + model->getId() + "'";
  }
  set<SBase*> todelete;
  for (unsigned int el=0; el<allElements->getSize(); el++) {
    SBase* element = static_cast<SBase*>(allElements->get(el));
    int type = element->getTypeCode();
    if (type==SBML_COMP_DELETION ||
        type==SBML_COMP_REPLACEDBY ||
        type==SBML_COMP_REPLACEDELEMENT ||
        type==SBML_COMP_PORT) {
          //Don't worry about SBML_COMP_SBASEREF because they're all children of one of the above types.
          SBaseRef* reference = static_cast<SBaseRef*>(element);
          ReplacedElement* re = static_cast<ReplacedElement*>(element);
          ret = reference->saveReferencedElement();
          if (ret != LIBSBML_OPERATION_SUCCESS) 
          {
            if (type != SBML_COMP_REPLACEDBY && doc) 
            {
              SBMLErrorLog* errlog = doc->getErrorLog();
              SBMLError* lasterr = const_cast<SBMLError*>
                (doc->getErrorLog()->getError(doc->getNumErrors()-1));
              if ( (errlog->contains(UnrequiredPackagePresent) || 
                    errlog->contains(RequiredPackagePresent))) 
              {
                if ( lasterr->getErrorId() == CompIdRefMustReferenceObject)
                {
                   //Change the error into a warning
                   string fullmsg = lasterr->getMessage() 
                     + "  However, this may be because of the unrecognized "
                     + "package present in this document:  ignoring this "
                     + "element and flattening anyway.";
                   errlog->remove(lasterr->getErrorId());
                   errlog->logPackageError("comp", 
                     CompIdRefMayReferenceUnknownPackage, getPackageVersion(), 
                     getLevel(), getVersion(), fullmsg, element->getLine(), 
                     element->getColumn(), LIBSBML_SEV_WARNING);
                }
                else if ( lasterr->getErrorId() == CompMetaIdRefMustReferenceObject)
                {
                   //Change the error into a warning
                   string fullmsg = lasterr->getMessage() 
                     + "  However, this may be because of the unrecognized "
                     + "package present in this document:  ignoring this "
                     + "element and flattening anyway.";
                   errlog->remove(lasterr->getErrorId());
                   errlog->logPackageError("comp", 
                     CompMetaIdRefMayReferenceUnknownPkg, getPackageVersion(), 
                     getLevel(), getVersion(), fullmsg, element->getLine(), 
                     element->getColumn(), LIBSBML_SEV_WARNING);
                }
              }
              //Whether or not we could figure out the error, we can always still continue flattening.
              todelete.insert(element);
              continue;
            }
            else {
              delete allElements;
              return ret;
            }
          }
          SBase* direct = reference->getDirectReference();
          bool adddirect = true;
          if (type == SBML_COMP_REPLACEDBY) {
            SBase* rbParent = reference->getParentSBMLObject();
            if (uniqueRefs.insert(rbParent).second == false) {
              if (doc) {
                string error = "Error discovered in CompModelPlugin::saveAllReferencedElements when checking " + modname + ": a <" + rbParent->getElementName() + "> ";
                if (direct->isSetId()) {
                  error += "with the id '" + rbParent->getId() + "'";
                  if (rbParent->isSetMetaId()) {
                    error += ", and the metaid '" + rbParent->getMetaId() + "'";
                  }
                }
                else if (rbParent->isSetMetaId()) {
                  error += "with the metaId '" + rbParent->getMetaId() + "'";
                }
                error += " has a <replacedBy> child and is also pointed to by a <port>, <deletion>, <replacedElement>, or one or more <replacedBy> objects.";
                doc->getErrorLog()->logPackageError("comp", CompNoMultipleReferences, getPackageVersion(), getLevel(), getVersion(), error);
              }
              delete allElements;
              return LIBSBML_OPERATION_FAILED;
            }
            adddirect = replacedBys.insert(direct).second;
          }
          if (type==SBML_COMP_REPLACEDELEMENT && re->isSetDeletion()) {
            adddirect = RE_deletions.insert(direct).second;
          }
          if (adddirect) {
            if (uniqueRefs.insert(direct).second == false) {
              if (doc) {
                string error = "Error discovered in CompModelPlugin::saveAllReferencedElements when checking " + modname + ": ";
                if (replacedBys.find(direct) != replacedBys.end()) {
                  error += "one or more <replacedBy> elements, plus a <deletion>, <replacedElement>, or <port> element";
                }
                else if (RE_deletions.find(direct) != RE_deletions.end()) {
                  error += "one or more <replacedElement> elements using a 'deletion' attribute, plus a <deletion>, <replacedElement>, or <port> element";
                }
                else {
                  error += "multiple <deletion>, <replacedElement>, and/or <port> elements";
                }
                error += " point directly to the <" + direct->getElementName() + "> ";
                if (direct->isSetId()) {
                  error += "with the id '" + direct->getId() + "'";
                  if (direct->isSetMetaId()) {
                    error += ", and the metaid '" + direct->getMetaId() + "'";
                  }
                  error += ".";
                }
                else if (direct->isSetMetaId()) {
                  error += "with the metaId '" + direct->getMetaId() + "'.";
                }
                doc->getErrorLog()->logPackageError("comp", CompNoMultipleReferences, getPackageVersion(), getLevel(), getVersion(), error);
              }
              delete allElements;
              return LIBSBML_OPERATION_FAILED;
            }
          }
    }
  }

  for(set<SBase*>::iterator el=todelete.begin(); el != todelete.end(); el++) {
    (*el)->removeFromParentAndDelete();
  }
  delete allElements;

  //Now call saveAllReferencedElements for all instantiated submodels.
  for (unsigned long sm=0; sm<getNumSubmodels(); ++sm) {
    Model* sub = getSubmodel((unsigned int)sm)->getInstantiation();
    if (sub==NULL) {
      return LIBSBML_OPERATION_FAILED;
    }
    CompModelPlugin* subplug = static_cast<CompModelPlugin*>(sub->getPlugin(getPrefix()));
    if (subplug==NULL) {
      return LIBSBML_OPERATION_FAILED;
    }
    ret = subplug->saveAllReferencedElements(uniqueRefs, replacedBys);
    if (ret != LIBSBML_OPERATION_SUCCESS) {
      return ret;
    }
  }

  return LIBSBML_OPERATION_SUCCESS;
}
Ejemplo n.º 20
0
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;
  
}
Ejemplo n.º 21
0
int Submodel::convertTimeAndExtentWith(const ASTNode* tcf, const ASTNode* xcf, const ASTNode* klmod)
{
  if (tcf==NULL && xcf==NULL) return LIBSBML_OPERATION_SUCCESS;
  Model* model = getInstantiation();
  if (model==NULL) {
    //getInstantiation sets its own error messages.
    return LIBSBML_OPERATION_FAILED;
  }
  ASTNode tcftimes(AST_TIMES);
  ASTNode tcfdiv(AST_DIVIDE);
  if (tcf != NULL) {
    tcftimes.addChild(tcf->deepCopy());
    tcfdiv.addChild(tcf->deepCopy());
  }
  ASTNode rxndivide(AST_DIVIDE);
  if (klmod != NULL) {
    ASTNode rxnref(AST_NAME);
    rxndivide.addChild(rxnref.deepCopy());
    rxndivide.addChild(klmod->deepCopy());
  }
  List* allElements = model->getAllElements();
  for (ListIterator iter = allElements->begin(); iter != allElements->end(); ++iter)
  {
    SBase* element = static_cast<SBase*>(*iter);
    assert(element != NULL);
    ASTNode* ast1 = NULL;
    ASTNode* ast2 = NULL;
    Constraint* constraint = NULL;
    Delay* delay = NULL;
    EventAssignment* ea = NULL;
    InitialAssignment* ia = NULL;
    KineticLaw* kl = NULL;
    Priority* priority = NULL;
    RateRule* rrule = NULL;
    Rule* rule = NULL;
    Submodel* submodel = NULL;
    Trigger* trigger = NULL;
    string cf = "";
    //Reaction math will be converted below, in the bits with the kinetic law.  But because of that, we need to handle references *to* the reaction:  even if it has no kinetic law, the units have changed, and this needs to be reflected by the flattening routine.
    if (rxndivide.getNumChildren() != 0 && element->getTypeCode()==SBML_REACTION && element->isSetId()) {
      rxndivide.getChild(0)->setName(element->getId().c_str());
      for (ListIterator iter = allElements->begin(); iter != allElements->end(); ++iter)
      {
        SBase* subelement = static_cast<SBase*>(*iter);
        subelement->replaceSIDWithFunction(element->getId(), &rxndivide);
      }
    }

    //Submodels need their timeConversionFactor and extentConversionFactor attributes converted.  We're moving top-down, so all we need to do here is fix the conversion factor attributes themselves, pointing them to new parameters if need be.
    if ((tcf !=NULL || xcf != NULL) && element->getTypeCode()==SBML_COMP_SUBMODEL) {
      submodel = static_cast<Submodel*>(element);
      if (tcf != NULL) {
        if (submodel->isSetTimeConversionFactor()) {
          createNewConversionFactor(cf, tcf, submodel->getTimeConversionFactor(), model);
          submodel->setTimeConversionFactor(cf);
        }
        else {
          submodel->setTimeConversionFactor(tcf->getName());
        }
      }
      if (xcf != NULL) {
        if (submodel->isSetExtentConversionFactor()) {
          createNewConversionFactor(cf, xcf, submodel->getExtentConversionFactor(), model);
          submodel->setExtentConversionFactor(cf);
        }
        else {
          submodel->setExtentConversionFactor(xcf->getName());
        }
      }
    }
    if (tcf==NULL) {
      if (klmod !=NULL && element->getTypeCode()==SBML_KINETIC_LAW) {
        kl = static_cast<KineticLaw*>(element);
        if (kl->isSetMath()) {
          ast1 = new ASTNode(AST_TIMES);
          ast1->addChild(klmod->deepCopy());
          ast1->addChild(kl->getMath()->deepCopy());
          kl->setMath(ast1);
          delete ast1;
        }
      }
    }
    else {
      // All math 'time' and 'delay' csymbols must still be converted.
      // Also, several constructs are modified directly.
      switch(element->getTypeCode()) {
        //This would be a WHOLE LOT SIMPLER if there was a 'hasMath' class in libsbml.  But even so, it would have to
        // handle the kinetic laws, rate rules, and delays separately.
      case SBML_KINETIC_LAW:
        //Kinetic laws are multiplied by 'klmod'.
        kl = static_cast<KineticLaw*>(element);
        ast1 = kl->getMath()->deepCopy();
        convertCSymbols(ast1, &tcfdiv, &tcftimes);
        if (klmod !=NULL) {
          kl = static_cast<KineticLaw*>(element);
          if (kl->isSetMath()) {
            ast2 = new ASTNode(AST_TIMES);
            ast2->addChild(klmod->deepCopy());
            ast2->addChild(ast1);
            kl->setMath(ast2);
            delete ast2;
          }
        }
        else {
          kl->setMath(ast1);
          delete ast1;
        }
        break;
      case SBML_DELAY:
        //Delays are multiplied by the time conversion factor.
        delay = static_cast<Delay*>(element);
        if (delay->isSetMath()) {
          ast1 = delay->getMath()->deepCopy();
          convertCSymbols(ast1, &tcfdiv, &tcftimes);
          tcftimes.addChild(ast1);
          delay->setMath(&tcftimes);
          tcftimes.removeChild(1);
          delete ast1;
        }
        break;
      case SBML_RATE_RULE:
        //Rate rules are divided by the time conversion factor.
        rrule = static_cast<RateRule*>(element);
        if (rrule->isSetMath()) {
          ast1 = rrule->getMath()->deepCopy();
          tcfdiv.insertChild(0, ast1);
          rrule->setMath(&tcfdiv);
          tcfdiv.removeChild(0);
          delete ast1;
        }
        //Fall through to:
      case SBML_ASSIGNMENT_RULE:
      case SBML_ALGEBRAIC_RULE:
        //Rules in general need csymbols converted.
        rule = static_cast<Rule*>(element);
        if (rule->isSetMath()) {
          ast1 = rule->getMath()->deepCopy();
          convertCSymbols(ast1, &tcfdiv, &tcftimes);
          rule->setMath(ast1);
          delete ast1;
        }
        break;
      case SBML_EVENT_ASSIGNMENT:
        //Event assignments need csymbols converted.
        ea = static_cast<EventAssignment*>(element);
        if (ea->isSetMath()) {
          ast1 = ea->getMath()->deepCopy();
          convertCSymbols(ast1, &tcfdiv, &tcftimes);
          ea->setMath(ast1);
          delete ast1;
        }
        break;
      case SBML_INITIAL_ASSIGNMENT:
        //Initial assignments need csymbols converted.
        ia = static_cast<InitialAssignment*>(element);
        if (ia->isSetMath()) {
          ast1 = ia->getMath()->deepCopy();
          convertCSymbols(ast1, &tcfdiv, &tcftimes);
          ia->setMath(ast1);
          delete ast1;
        }
        break;
      case SBML_CONSTRAINT:
        //Constraints need csymbols converted.
        constraint = static_cast<Constraint*>(element);
        if (constraint->isSetMath()) {
          ast1 = constraint->getMath()->deepCopy();
          convertCSymbols(ast1, &tcfdiv, &tcftimes);
          constraint->setMath(ast1);
          delete ast1;
        }
        break;
      case SBML_PRIORITY:
        //Priorities need csymbols converted.
        priority = static_cast<Priority*>(element);
        if (priority->isSetMath()) {
          ast1 = priority->getMath()->deepCopy();
          convertCSymbols(ast1, &tcfdiv, &tcftimes);
          priority->setMath(ast1);
          delete ast1;
        }
        break;
      case SBML_TRIGGER:
        //Triggers need csymbols converted.
        trigger = static_cast<Trigger*>(element);
        if (trigger->isSetMath()) {
          ast1 = trigger->getMath()->deepCopy();
          convertCSymbols(ast1, &tcfdiv, &tcftimes);
          trigger->setMath(ast1);
          delete ast1;
        }
        break;
      default:
        //Do nothing!  If we wanted to call a plugin routine, this would be the place.  The only other alternative is to #ifdef some code in here that deals with the math-containing package objects explicitly.  Which might be the best option, all told.
        break;
      }
    }
  }

  delete allElements;

  return LIBSBML_OPERATION_SUCCESS;
}
Ejemplo n.º 22
0
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;
}