bool hasActualErrors(SBMLDocument* document)
{
  document->checkConsistency();
  for (unsigned int e=0; e<document->getNumErrors(); e++) {
    if (document->getError(e)->getSeverity() >= LIBSBML_SEV_ERROR) return true;
  }
#ifdef USE_COMP
  CompModelPlugin* compmod = static_cast<CompModelPlugin*>(document->getModel()->getPlugin("comp"));
  if (compmod != NULL && compmod->getNumSubmodels() > 0) {
    SBMLDocument flat(*document);
    ConversionProperties* props = new ConversionProperties();
    props->addOption("flatten comp");
    SBMLConverter* converter = 
      SBMLConverterRegistry::getInstance().getConverterFor(*props);
    converter->setDocument(&flat);
    int result = converter->convert();
    flat.checkConsistency();
    bool flaterrors = false;
    SBMLErrorLog* errlog = document->getErrorLog();
    for (unsigned int e=0; e<flat.getNumErrors(); e++) {
      if (flat.getError(e)->getSeverity() >= LIBSBML_SEV_ERROR) {
        flaterrors = true;
        errlog->add(*(flat.getError(e)));
      }
    }
    if (flaterrors) return true;
 }
#endif
  return false;
}
Exemple #2
0
//Deprecated function
int Replacing::performReplacement()
{
  set<SBase*> toremove;
  set<SBase*>* removed = NULL;
  CompModelPlugin* cmp = NULL;
  SBase* parent = getParentSBMLObject();
  while (parent != NULL && parent->getTypeCode() != SBML_DOCUMENT) {
    if (parent->getTypeCode() == SBML_COMP_MODELDEFINITION ||
        parent->getTypeCode() == SBML_MODEL) {
          cmp = static_cast<CompModelPlugin*>(parent->getPlugin("comp"));
          if (cmp != NULL) {
            removed = cmp->getRemovedSet();
          }
    }
    parent = parent->getParentSBMLObject();
  }
  int ret = performReplacementAndCollect(removed, &toremove);
  if (ret != LIBSBML_OPERATION_SUCCESS) {
    return ret;
  }
  if (cmp == NULL) {
    return LIBSBML_INVALID_OBJECT;
  }
  return cmp->removeCollectedElements(removed, &toremove);
}
int CompModelPlugin::collectDeletionsAndDeleteSome(set<SBase*>* removed, set<SBase*>* toremove)
{
  int ret = LIBSBML_OPERATION_SUCCESS;
  SBMLDocument* doc = getSBMLDocument();
  Model* model = static_cast<Model*>(getParentSBMLObject());
  if (model==NULL) {
    if (doc) {
      string error = "Unable to attempt to perform deletions in CompModelPlugin::collectDeletionsAndDeleteSome: no parent model could be found for the given 'comp' model plugin element.";
      doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error);
    }
    return LIBSBML_OPERATION_FAILED;
  }

  //Since deletions only exist in submodels, loop through the submodels.
  for (unsigned int sub=0; sub<getNumSubmodels(); sub++) {
    Submodel* submodel = getSubmodel(sub);
    //First perform any deletions
    for (unsigned int d=0; d<submodel->getNumDeletions(); d++) {
      Deletion* deletion = submodel->getDeletion(d);
      SBase* todel = deletion->getReferencedElement();
      if (todel && (todel->getTypeCode() == SBML_COMP_DELETION ||
                    todel->getTypeCode() == SBML_COMP_REPLACEDBY ||
                    todel->getTypeCode() == SBML_COMP_REPLACEDELEMENT ||
                    todel->getTypeCode() == SBML_LOCAL_PARAMETER) )
      {
        //Go ahead and delete it!
        set<SBase*> newToRemove;
        newToRemove.insert(todel);
        removeCollectedElements(removed, &newToRemove);
      }
      else {
        //Otherwise, just collect it.
        ret = deletion->collectDeletions(removed, toremove);
        if (ret!=LIBSBML_OPERATION_SUCCESS) {
          return ret;
        }
      }
    }
    //Next collect any deletions in that instantiated submodel (any that weren't just deleted)
    Model* mod = submodel->getInstantiation();
    if (mod==NULL) {
      //getInstantiation sets its own error messages.
      return LIBSBML_OPERATION_FAILED;
    }
    CompModelPlugin* modplug = static_cast<CompModelPlugin*>(mod->getPlugin(getPrefix()));
    if (modplug==NULL) {
      if (doc) {
        //Shouldn't happen:  'getInstantiation' turns on the comp plugin.
        string error = "Unable to rename elements in CompModelPlugin::collectDeletionsAndDeleteSome: no valid 'comp' plugin for the model instantiated from submodel " + submodel->getId();
        doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error);
      }
      return LIBSBML_OPERATION_FAILED;
    }
    modplug->collectDeletionsAndDeleteSome(removed, toremove);
  }
  return ret;
}
List* 
Submodel::getAllInstantiatedElements()
{
  Model* inst = getInstantiation();
  if (inst==NULL) return NULL;
  List* allElements = inst->getAllElements();
  vector<List*> sublists;
  CompModelPlugin* instp = static_cast<CompModelPlugin*>(inst->getPlugin(getPrefix()));
  for (unsigned int sm=0; sm<instp->getNumSubmodels(); sm++) {
    Submodel* subm=instp->getSubmodel(sm);
    if (subm==NULL) return NULL;
    List* sublist = subm->getAllInstantiatedElements();
    sublists.push_back(sublist);
  }
  for (size_t l=0; l<sublists.size(); l++) {
    allElements->transferFrom(sublists[l]);
    delete sublists[l];
  }  
  return allElements;
}
SBase* 
ReplacedElement::getReferencedElementFrom(Model* model)
{
  SBMLDocument* doc = getSBMLDocument();
  SBase* referent = Replacing::getReferencedElementFrom(model);
  if (referent != NULL) return referent;
  if (!isSetDeletion()) {
    //In this case, something else went wrong in getReferencedElementFrom, which will have set its own error message.
    return NULL;
  }
  model = getParentModel(this);
  if (model==NULL) {
    if (doc) {
      string error = "In ReplacedElement::getReferencedElementFrom, unable to find referenced deletion '" + getDeletion() + "' for <replacedElement>: no parent model could be found.";
      doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    }
    return NULL;
  }
  CompModelPlugin* mplugin = static_cast<CompModelPlugin*>(model->getPlugin(getPrefix()));
  if (mplugin==NULL) {
    if (doc) {
      string error = "In ReplacedElement::getReferencedElementFrom, unable to find referenced deletion '" + getDeletion() + "' for <replacedElement>: no 'comp' plugin for the parent model could be found.";
      doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    }
    return NULL;
  }
  Submodel* submod = mplugin->getSubmodel(getSubmodelRef());
  if (submod==NULL) {
    if (doc) {
      string error = "In ReplacedElement::getReferencedElementFrom, unable to find referenced deletion '" + getDeletion() + "' for <replacedElement>: no such submodel '" + getSubmodelRef() + "'.";
      doc->getErrorLog()->logPackageError("comp", CompReplacedElementSubModelRef, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    }
    return NULL;
  }
  SBase* ret = submod->getDeletion(getDeletion());
  if (ret==NULL && doc) {
    string error = "In ReplacedElement::getReferencedElementFrom, unable to find referenced deletion '" + getDeletion() + "' for <replacedElement>: no deletion with that ID exists in the model.";
    doc->getErrorLog()->logPackageError("comp", CompDeletionMustReferenceObject, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
  }
  return ret;
}
Model* CompModelPlugin::flattenModel() const
{
  //First make a copy of our parent (the model to be flattened):
  const Model* parent = static_cast<const Model*>(getParentSBMLObject());
  
  if (parent==NULL) {
    return NULL;
  }
  //doc needs to be non-const so that the error messages can be updated.  Otherwise, nothing changes.
  SBMLDocument* doc = const_cast<SBMLDocument*>(getSBMLDocument());
  if (doc==NULL) {
    return NULL;
  }

  //Set the original document so that it can find the model definitions 
  //and external model definitions while we flatten.
  Model* flat = parent->clone();
  flat->setSBMLDocument(doc);
  CompModelPlugin* flatplug = 
    static_cast<CompModelPlugin*>(flat->getPlugin(getPrefix()));

  // Now instantiate its submodels and 
  // follow all renaming/deletion/replacement rules.
  vector<const Model*> submods;
  int success = flatplug->instantiateSubmodels();

  if (success != LIBSBML_OPERATION_SUCCESS) {
    //instantiateSubmodels sets its own error messages.
    delete flat;
    return NULL;
  }

  //Now start the aggregation process.  
  //This goes from the bottom up, calling 'appendFrom' iteratively 
  //(from the plugin).
  for (unsigned int sm=0; sm<flatplug->getNumSubmodels(); sm++) 
  {
    Model* submodel = flatplug->getSubmodel(sm)->getInstantiation();
    if (submodel==NULL) {
      //getInstantiation should be calling a cached value by now, but if not, it will set its own error messages.
      delete flat;
      return NULL;
    }
    CompModelPlugin* submodplug = 
      static_cast<CompModelPlugin*>(submodel->getPlugin(getPrefix()));

    if (submodplug != NULL) {
      //Strip the ports from the submodel, as we no longer need them.
      while (submodplug->getNumPorts() > 0) 
      {
        delete submodplug->removePort(0);
      }
    }
    success = flat->appendFrom(submodel);
    if (success != LIBSBML_OPERATION_SUCCESS) {
      string error = "Unable to flatten model in CompModelPlugin::flattenModel: appending elements from the submodel '" + submodel->getId() + "' to the elements of the parent model failed.";
      doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error);
      delete flat;
      return NULL;
    }
  }

  // Now we clear the saved referenced elements in the local Port objects, 
  // but point them to the new object if necessary.
  flatplug->resetPorts();

  // Next, strip the package info from 'flat'.  
  // We're going to remove everything but the Ports:
  flatplug->mListOfSubmodels.clear();
  flatplug->clearReplacedElements();
  flatplug->unsetReplacedBy();
  
  List* allelements = flat->getAllElements();
  
  vector<SBase*> nonReplacedElements;
  
  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_REPLACEDBY ||
          type==SBML_COMP_REPLACEDELEMENT ||
          type==SBML_COMP_SBASEREF)) 
    {
            nonReplacedElements.push_back(element);
    }
  }

  // delete the list
  delete allelements;

  for (unsigned int el=0; el<nonReplacedElements.size(); el++) 
  {
    SBase* element = nonReplacedElements[el];
    CompSBasePlugin* elplug = 
      static_cast<CompSBasePlugin*>(element->getPlugin(getPrefix()));
    if (elplug != NULL) 
    {
      elplug->clearReplacedElements();
      elplug->unsetReplacedBy();
    }
  }



  //Finally, unset the document again.
  flat->setSBMLDocument(NULL);

  return flat;
}
int CompModelPlugin::collectRenameAndConvertReplacements(set<SBase*>* removed, set<SBase*>* toremove)
{
  int ret = LIBSBML_OPERATION_SUCCESS;
  SBMLDocument* doc = getSBMLDocument();
  Model* model = static_cast<Model*>(getParentSBMLObject());
  if (model==NULL) {
    if (doc) {
      string error = "Unable to perform replacements in CompModelPlugin::collectRenameAndConvertReplacements: no parent model could be found for the given 'comp' model plugin element.";
      doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error);
    }
    return LIBSBML_OPERATION_FAILED;
  }
  List* allElements = model->getAllElements();
  vector<ReplacedElement*> res;
  vector<ReplacedBy*> rbs;
  //Collect replaced elements and replaced by's.
  for (unsigned int e=0; e<allElements->getSize(); e++) {
    SBase* element = static_cast<SBase*>(allElements->get(e));
    int type = element->getTypeCode();
    if (type==SBML_COMP_REPLACEDELEMENT) {
      ReplacedElement* reference = static_cast<ReplacedElement*>(element);
      res.push_back(reference);
    }
    if (type==SBML_COMP_REPLACEDBY) {
      ReplacedBy* reference = static_cast<ReplacedBy*>(element);
      rbs.push_back(reference);
    }
  }
  delete allElements;

  //ReplacedElement replacements
  for (size_t re=0; re<res.size(); re++) {
    ret = res[re]->performReplacementAndCollect(removed, toremove);
    if (ret != LIBSBML_OPERATION_SUCCESS) {
      return ret;
    }
  }

  //Now do the same thing for anything left over in the submodels
  for (unsigned int sub=0; sub<getNumSubmodels(); sub++) {
    Submodel* submodel = getSubmodel(sub);
    Model* mod = submodel->getInstantiation();
    if (mod==NULL) return LIBSBML_OPERATION_FAILED;
    CompModelPlugin* modplug = static_cast<CompModelPlugin*>(mod->getPlugin(getPrefix()));
    if (modplug==NULL) return LIBSBML_OPERATION_FAILED;
    //'left behind' converions (not LaHaye-style)
    ret = submodel->convertTimeAndExtent();
    if (ret != LIBSBML_OPERATION_SUCCESS) return ret;
    ret = modplug->collectRenameAndConvertReplacements(removed, toremove);
    if (ret != LIBSBML_OPERATION_SUCCESS) return ret;
  }

  //Perform ReplacedBy replacements *after* the submodels are done, so that the topmost-level names take precedence.
  for (size_t rb=0; rb<rbs.size(); rb++) {
    ret = rbs[rb]->performReplacementAndCollect(removed, toremove);
    if (ret != LIBSBML_OPERATION_SUCCESS) {
      return ret;
    }
  }

  return ret;
}
Exemple #8
0
int 
Replacing::saveReferencedElement()
{
  SBMLDocument* doc = getSBMLDocument();
  if (!isSetSubmodelRef()) {
    if (doc) {
      string error = "Unable to find referenced element in Replacing::saveReferencedElement: the given <" + getElementName() + "> element";
      if (isSetId()) {
        error += " '" + getId() + "'";
      }
      error += " has no 'submodelRef' attribute.";
      doc->getErrorLog()->logPackageError("comp", CompReplacedElementAllowedAttributes, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    }
    return LIBSBML_INVALID_OBJECT;
  }
  Model* model = getParentModel(this);
  if (model==NULL) {
    if (doc) {
      string error = "Unable to find referenced element in Replacing::saveReferencedElement: no parent model could be found for the given <" + getElementName() + "> element";
      if (isSetId()) {
        error += " '" + getId() + "'.";
      }
      doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    }
    return LIBSBML_OPERATION_FAILED;
  }
  CompModelPlugin* cmp = static_cast<CompModelPlugin*>(model->getPlugin(getPrefix()));
  if (cmp==NULL) {
    if (doc) {
      string error = "Unable to find referenced element in Replacing::saveReferencedElement: no 'comp' plugin for the parent model could be found for the given <" + getElementName() + "> element";
      if (isSetId()) {
        error += " '" + getId() + "'.";
      }
      doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    }
    return LIBSBML_OPERATION_FAILED;
  }
  Submodel* submod = cmp->getSubmodel(getSubmodelRef());
  if (submod==NULL) {
    if (doc) {
      string error = "Unable to find referenced element for the given <" + getElementName() + "> element";
      if (isSetId()) {
        error += " '" + getId() + "'";
      }
      error += " in Replacing::saveReferencedElement: the submodelRef '" + getSubmodelRef() + "' could not be found in the model.";
      int errnumber = CompReplacedElementSubModelRef;
      if (getTypeCode() == SBML_COMP_REPLACEDBY) {
        errnumber = CompReplacedBySubModelRef;
      }
      doc->getErrorLog()->logPackageError("comp", errnumber, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    }
    return LIBSBML_INVALID_ATTRIBUTE_VALUE;
  }
  Model* inst = submod->getInstantiation();
  if (inst==NULL) {
    //getInstantiation sets it own error messages.
    return LIBSBML_OPERATION_FAILED;
  }
  mReferencedElement = getReferencedElementFrom(inst);
  if (mDirectReference==NULL) {
    mDirectReference = mReferencedElement;
  }
  //getReferencedElement* set their own error messages:
  if (mReferencedElement==NULL) {
    return LIBSBML_OPERATION_FAILED;
  }
  if (mReferencedElement->getTypeCode()==SBML_COMP_PORT) {
    mReferencedElement = static_cast<Port*>(mReferencedElement)->getReferencedElement();
  }
  if (mReferencedElement==NULL) {
    return LIBSBML_OPERATION_FAILED;
  }
  return LIBSBML_OPERATION_SUCCESS;
}
int 
Submodel::instantiate()
{
  SBMLDocument* doc = getSBMLDocument();
  SBMLDocument* rootdoc = doc;
  if (doc==NULL) 
  {
    return LIBSBML_OPERATION_FAILED;
  }

  CompSBMLDocumentPlugin* docplugin = 
    static_cast<CompSBMLDocumentPlugin*>(doc->getPlugin(getPrefix()));
  if (docplugin==NULL)
  {
    return LIBSBML_OPERATION_FAILED;
  }

  SBase* parent  = getParentSBMLObject();
  string parentmodelname = "";
  string parentURI = "";
  set<string> uniqueModels;
  while (parent != NULL && parent->getTypeCode() != SBML_DOCUMENT) {
    if (parent->getTypeCode() == SBML_COMP_SUBMODEL) {
      const Submodel* parentsub = static_cast<const Submodel*>(parent);
      uniqueModels.insert(parentsub->mInstantiationOriginalURI + "::" + parentsub->getModelRef());
      if (parentURI=="") {
        parentURI=parentsub->mInstantiationOriginalURI;
      }
    }
    if (parent->getTypeCode() == SBML_MODEL ||
      parent->getTypeCode() == SBML_COMP_MODELDEFINITION)
    {
      if (parentmodelname == "") {
        parentmodelname = parent->getId();
      }
    }
    rootdoc = parent->getSBMLDocument();
    parent = parent->getParentSBMLObject();
  }

  if (mInstantiatedModel != NULL) 
  {
    delete mInstantiatedModel;
    mInstantiatedModel = NULL;
    mInstantiationOriginalURI.clear();
  }

  if (!hasRequiredAttributes()) {
    string error = "Instantiation error in Submodel::instantiate:  ";
    if (!isSetId()) {
      error += "A submodel in model '" + getParentModel(this)->getId() + "' does not have an 'id' attribute.";
    }
    else if (!isSetModelRef()) {
      error += "The submodel '" + getId() + "' does not have a 'modelRef' attribute.";
    }
    rootdoc->getErrorLog()->logPackageError("comp", CompSubmodelAllowedAttributes, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    return LIBSBML_INVALID_OBJECT;
  }

  SBase* origmodel = docplugin->getModel(getModelRef());
  
  if (origmodel==NULL) {
    string error = "In Submodel::instantiate, unable to instantiate submodel '" + getId() + "' because the referenced model ('" + getModelRef() +"') does not exist.";
    rootdoc->getErrorLog()->logPackageError("comp", CompSubmodelMustReferenceModel, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    return LIBSBML_INVALID_OBJECT;
  }
  ExternalModelDefinition* extmod;
  SBMLDocument* origdoc = NULL;
  string newmodel = parentURI + "::" + getModelRef();
  
  set<pair<string, string> > parents;
  switch(origmodel->getTypeCode()) 
  {
  case SBML_MODEL:
  case SBML_COMP_MODELDEFINITION:
    origdoc = origmodel->getSBMLDocument();
    mInstantiatedModel = static_cast<Model*>(origmodel)->clone();
    if (uniqueModels.insert(newmodel).second == false) {
      //Can't instantiate this model, because we are already a child of it.
      string error = "Error in Submodel::instantiate:  cannot instantiate submodel '" + getId() + "' in model '" + parentmodelname + "' because it references the model '" + getModelRef() + "', which is already an ancestor of the submodel.";
      rootdoc->getErrorLog()->logPackageError("comp", CompSubmodelCannotReferenceSelf, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
      return LIBSBML_OPERATION_FAILED;
    }
    mInstantiationOriginalURI = parentURI;
    break;
  case SBML_COMP_EXTERNALMODELDEFINITION:
    extmod = static_cast<ExternalModelDefinition*>(origmodel);
    if (extmod==NULL) 
    {
      //No error message:  it should be impossible, if origmodel has the type code 'external model definition', for it to not be castable to an external model definition.
      mInstantiatedModel = NULL;
      mInstantiationOriginalURI = "";
      return LIBSBML_OPERATION_FAILED;
    }
    mInstantiatedModel = extmod->getReferencedModel(rootdoc, parents);
    if (mInstantiatedModel == NULL) 
    {
      string error = "In Submodel::instantiate, unable to instantiate submodel '" + getId() + "' because the external model definition it referenced (model '" + getModelRef() +"') could not be resolved.";
      rootdoc->getErrorLog()->logPackageError("comp", CompSubmodelMustReferenceModel, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
      mInstantiationOriginalURI = "";
      return LIBSBML_OPERATION_FAILED;
    }
    mInstantiationOriginalURI = extmod->getSource();
    origdoc = mInstantiatedModel->getSBMLDocument();
    newmodel = extmod->getSource() + "::" + getModelRef();
    if (uniqueModels.insert(newmodel).second == false) {
      //Can't instantiate this model, because we are already a child of it.
      string error = "Error in Submodel::instantiate:  cannot instantiate submodel '" + getId() + "' in model '" + parentmodelname + "' because it references the model '" + getModelRef() + "', which is already an ancestor of the submodel.";
      rootdoc->getErrorLog()->logPackageError("comp", CompSubmodelCannotReferenceSelf, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
      mInstantiatedModel = NULL;
      mInstantiationOriginalURI = "";
      return LIBSBML_OPERATION_FAILED;
    }
    mInstantiatedModel = mInstantiatedModel->clone();
    mInstantiationOriginalURI = extmod->getSource();
    break;
  default:
    //Should always be one of the above, unless someone extends one of the above and doesn't tell us.
    string error = "Instantiation error in Submodel::instantiate:  unable to parse the model '" + origmodel->getId() + "', as it was not of the type 'model' 'modelDefinition', or 'externalModelDefinition'.  The most likely cause of this situation is if some other package extended one of those three types, but the submodel code was not updated.";
    rootdoc->getErrorLog()->logPackageError("comp", CompUnresolvedReference, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    mInstantiatedModel = NULL;
    mInstantiationOriginalURI = "";
    return LIBSBML_OPERATION_FAILED;
  }
  
  if (mInstantiatedModel==NULL) 
  {
    string error = "Instantiation error in Submodel::instantiate:  unable to create a valid copy of model '" + getModelRef() + "'.";
    rootdoc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    mInstantiationOriginalURI = "";
    return LIBSBML_OPERATION_FAILED;
  }

  mInstantiatedModel->connectToParent(this);
  mInstantiatedModel->setSBMLDocument(origdoc);
  mInstantiatedModel->enablePackage(getPackageURI(), getPrefix(), true);
  CompModelPlugin* instmodplug = 
    static_cast<CompModelPlugin*>(mInstantiatedModel->getPlugin(getPrefix()));
  if (instmodplug == NULL)
  {
    mInstantiatedModel->enablePackageInternal(getPackageURI(), getPrefix(), true);
  }

  // call all registered callbacks
  std::vector<ModelProcessingCallbackData*>::iterator it = mProcessingCBs.begin();
  while(it != mProcessingCBs.end())
  {
    ModelProcessingCallbackData* current = *it;
    int result = current->cb(mInstantiatedModel, rootdoc->getErrorLog(), current->data);
    if (result != LIBSBML_OPERATION_SUCCESS)
      return result;
    ++it;
  }

  
  CompModelPlugin* origmodplug = 
    static_cast<CompModelPlugin*>(rootdoc->getModel()->getPlugin(getPrefix()));

  instmodplug = 
    static_cast<CompModelPlugin*>(mInstantiatedModel->getPlugin(getPrefix()));
  
  if (instmodplug == NULL)
    return LIBSBML_OPERATION_SUCCESS;

  // if we have a transformer specified, then we need to propagate it, so it can
  // be used
  if (origmodplug->isSetTransformer())
  {
    if (instmodplug != NULL)
      instmodplug->setTransformer(origmodplug->getTransformer());
  }

  
  for (unsigned int sub=0; sub<instmodplug->getNumSubmodels(); sub++) 
  {
    Submodel* instsub = instmodplug->getSubmodel(sub);
    int ret = instsub->instantiate();
    if (ret != LIBSBML_OPERATION_SUCCESS) {
      //'instantiate' already sets its own error messages.
      delete mInstantiatedModel;
      mInstantiatedModel = NULL;
      mInstantiationOriginalURI = "";
      return ret;
    }
  }

  return LIBSBML_OPERATION_SUCCESS;
}
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;
}
int main(int argc,char** argv) 
{
  int retval = 0;
  SBMLNamespaces sbmlns(3,1,"comp",1);

  // create the document
  SBMLDocument *document = new SBMLDocument(&sbmlns);

  //Create our submodel
  CompSBMLDocumentPlugin* compdoc
      = static_cast<CompSBMLDocumentPlugin*>(document->getPlugin("comp"));
  compdoc->setRequired(true);
  ModelDefinition* mod1 = compdoc->createModelDefinition();
  mod1->setId("enzyme");
  mod1->setName("enzyme");
  Compartment* comp=mod1->createCompartment();
  comp->setSpatialDimensions((unsigned int)3);
  comp->setConstant(true);
  comp->setId("comp");
  comp->setSize(1L);
  Species spec(&sbmlns);
  spec.setCompartment("comp");
  spec.setHasOnlySubstanceUnits(false);
  spec.setConstant(false);
  spec.setBoundaryCondition(false);
  spec.setId("S");
  mod1->addSpecies(&spec);
  spec.setId("E");
  mod1->addSpecies(&spec);
  spec.setId("D");
  mod1->addSpecies(&spec);
  spec.setId("ES");
  mod1->addSpecies(&spec);
  Reaction rxn(&sbmlns);
  rxn.setReversible(true);
  rxn.setFast(false);
  Reaction rxn2(rxn);
  rxn.setId("J0");
  rxn2.setId("J1");
  SpeciesReference sr(&sbmlns);
  sr.setConstant(true);
  sr.setStoichiometry(1);
  sr.setSpecies("S");
  rxn.addReactant(&sr);
  sr.setSpecies("E");
  rxn.addReactant(&sr);
  rxn2.addProduct(&sr);
  sr.setSpecies("ES");
  rxn.addProduct(&sr);
  rxn2.addReactant(&sr);
  sr.setSpecies("D");
  rxn2.addProduct(&sr);

  mod1->addReaction(&rxn);
  mod1->addReaction(&rxn2);

  // create the Model
  Model* model=document->createModel();
  model->setId("aggregate");
  
  // Create a submodel
  CompModelPlugin* mplugin = static_cast<CompModelPlugin*>(model->getPlugin("comp"));
  Submodel* submod1 = mplugin->createSubmodel();
  submod1->setId("submod1");
  submod1->setModelRef("enzyme");

  Submodel submod2;
  submod2.setId("submod2");
  submod2.setModelRef("enzyme");
  mplugin->addSubmodel(&submod2);

  writeSBMLToFile(document,"eg-simple-aggregate.xml");
  writeSBMLToFile(document,"enzyme_model.xml");
  delete document;
  document = readSBMLFromFile("enzyme_model.xml");
  if (document == NULL)
  {
    cout << "Error reading back in file." << endl;
    retval = -1;
  }
  else
  {
    document->setConsistencyChecks(LIBSBML_CAT_UNITS_CONSISTENCY, false);
    document->checkConsistency();
    if (document->getErrorLog()->getNumFailsWithSeverity(2) > 0
        || document->getErrorLog()->getNumFailsWithSeverity(3) > 0)
    {
      stringstream errorstream;
      document->printErrors(errorstream);
      cout << "Errors encoutered when round-tripping  SBML file: \n"
           <<  errorstream.str() << endl;
      retval = -1;
    }
    writeSBMLToFile(document, "enzyme_model_rt.xml");
    delete document;
  }
#ifdef WIN32
  if (retval != 0)
  {
    cout << "(Press any key to exit.)" << endl;
    _getch();
  }
#endif
  return retval;
}
int main(int argc,char** argv)
{
  int retval = 0;
  SBMLNamespaces sbmlns(3,1,"comp",1);

  // create the document
  SBMLDocument *document = new SBMLDocument(&sbmlns);

  //Define the external model definition
  CompSBMLDocumentPlugin* compdoc
      = static_cast<CompSBMLDocumentPlugin*>(document->getPlugin("comp"));
  compdoc->setRequired(true);
  ExternalModelDefinition* extmod = compdoc->createExternalModelDefinition();
  extmod->setId("ExtMod1");
  extmod->setSource("enzyme_model.xml");
  extmod->setModelRef("enzyme");

  //Define the 'simple' model
  ModelDefinition* mod1 = compdoc->createModelDefinition();
  mod1->setId("simple");
  Compartment* comp=mod1->createCompartment();
  comp->setSpatialDimensions((unsigned int)3);
  comp->setConstant(true);
  comp->setId("comp");
  comp->setSize(1L);

  // We have to construct it this way because we get the comp
  // plugin from it later.
  Species spec(&sbmlns);
  spec.setCompartment("comp");
  spec.setHasOnlySubstanceUnits(false);
  spec.setConstant(false);
  spec.setBoundaryCondition(false);
  spec.setId("S");
  spec.setInitialConcentration(5);
  mod1->addSpecies(&spec);
  spec.setId("D");
  spec.setInitialConcentration(10);
  mod1->addSpecies(&spec);

  Reaction rxn(&sbmlns);
  rxn.setReversible(true);
  rxn.setFast(false);
  rxn.setId("J0");

  SpeciesReference sr(&sbmlns);
  sr.setConstant(true);
  sr.setStoichiometry(1);
  sr.setSpecies("S");
  rxn.addReactant(&sr);
  sr.setSpecies("D");
  rxn.addProduct(&sr);

  mod1->addReaction(&rxn);

  CompModelPlugin* mod1plug
      = static_cast<CompModelPlugin*>(mod1->getPlugin("comp"));
  Port port;
  port.setId("S_port");
  port.setIdRef("S");
  mod1plug->addPort(&port);

  Port* port2 = mod1plug->createPort();
  port2->setId("D_port");
  port2->setIdRef("D");

  port.setId("comp_port");
  port.setIdRef("comp");
  mod1plug->addPort(&port);

  port.setId("J0_port");
  port.setIdRef("J0");
  mod1plug->addPort(&port);

  // create the Model
  Model* model=document->createModel();
  model->setId("complexified");
  
  // Set the submodels
  CompModelPlugin* mplugin
      = static_cast<CompModelPlugin*>(model->getPlugin("comp"));
  Submodel* submod1 = mplugin->createSubmodel();
  submod1->setId("A");
  submod1->setModelRef("ExtMod1");
  Submodel* submod2 = mplugin->createSubmodel();
  submod2->setId("B");
  submod2->setModelRef("simple");
  Deletion* del = submod2->createDeletion();
  del->setPortRef("J0_port");

  // Synchronize the compartments
  Compartment* mcomp=model->createCompartment();
  mcomp->setSpatialDimensions((unsigned int)3);
  mcomp->setConstant(true);
  mcomp->setId("comp");
  mcomp->setSize(1L);
  CompSBasePlugin* compartplug
      = static_cast<CompSBasePlugin*>(mcomp->getPlugin("comp"));
  ReplacedElement re;
  re.setIdRef("comp");
  re.setSubmodelRef("A");
  compartplug->addReplacedElement(&re);
  re.setSubmodelRef("B");
  re.unsetIdRef();
  re.setPortRef("comp_port");
  compartplug->addReplacedElement(&re);

  //Synchronize the species
  spec.setId("S");
  spec.unsetInitialConcentration();
  CompSBasePlugin* specplug
      = static_cast<CompSBasePlugin*>(spec.getPlugin("comp"));
  ReplacedElement* sre = specplug->createReplacedElement();
  sre->setSubmodelRef("A");
  sre->setIdRef("S");
  ReplacedBy* srb = specplug->createReplacedBy();
  srb->setSubmodelRef("B");
  srb->setPortRef("S_port");
  model->addSpecies(&spec);

  spec.setId("D");
  sre->setIdRef("D");
  srb->setPortRef("D_port");
  model->addSpecies(&spec);

  writeSBMLToFile(document,"eg-ports.xml");
  writeSBMLToFile(document,"spec_example3.xml");
  delete document;
  document = readSBMLFromFile("spec_example3.xml");
  if (document == NULL)
  {
    cout << "Error reading back in file." << endl;
    retval = -1;
  }
  else
  {
    document->setConsistencyChecks(LIBSBML_CAT_UNITS_CONSISTENCY, false);
    document->checkConsistency();
    if (document->getErrorLog()->getNumFailsWithSeverity(2) > 0
        || document->getErrorLog()->getNumFailsWithSeverity(3) > 0)
    {
      stringstream errorstream;
      document->printErrors(errorstream);
      cout << "Errors encoutered when round-tripping  SBML file: \n"
           <<  errorstream.str() << endl;
      retval = -1;
    }
    writeSBMLToFile(document, "spec_example3_rt.xml");
    delete document;
  }
#ifdef WIN32
  if (retval != 0)
  {
    cout << "(Press any key to exit.)" << endl;
    _getch();
  }
#endif
  return retval;
}
/*
 * Loop through all Submodels in this Model, instantiate all of them, 
 * perform all deletions, and synchronize all replacements.  
 * The resulting models are stored in the Submodel objects, 
 * and available from 'Submodel::getInstantiation()'
 */
int 
CompModelPlugin::instantiateSubmodels()
{
  Model* model = static_cast<Model*>(getParentSBMLObject());
  
  if (model==NULL) 
    return LIBSBML_INVALID_OBJECT;
  
  int ret;

  // First we instantiate all the submodels.  
  // This acts recursively downward through the stack.
  for (unsigned int sub=0; sub<mListOfSubmodels.size(); sub++) 
  {
    Submodel* submodel = mListOfSubmodels.get(sub);
    // Instead of 'instantiate', since we might have already 
    // been instantiated ourselves from above.
    Model* submodinst = submodel->getInstantiation(); 
    
    if (submodinst == NULL ) {
      //'getInstantiation' already sets any errors that might have occurred.
      return LIBSBML_OPERATION_FAILED;
    }
    
    // if we have a transformer specified, then we need to propagate it, so it can
    // be used
    if (isSetTransformer())
    {
      CompModelPlugin* other = dynamic_cast<CompModelPlugin*>(submodinst->getPlugin("comp"));
      if (other != NULL)
        other->setTransformer(getTransformer());
    }
  }

  // Next, recursively find all the targets of SBaseRef elements 
  // and save them, since we're about to rename everything and 
  // we won't be able to find things by name any more.
  ret = saveAllReferencedElements(); 
  if (ret != LIBSBML_OPERATION_SUCCESS) {
    //saveAllReferencedElements sets any errors.
    return ret;
  }

  mRemoved.clear();
  set<SBase*> toremove;

  // Collect deletions (top-down):  
  // need to do this before renaming in case we delete a local parameter.
  ret = collectDeletionsAndDeleteSome(&mRemoved, &toremove);

  if (ret != LIBSBML_OPERATION_SUCCESS) {
    return ret;
  }

  //Next, we rename *all* the elements so everything is unique.
  ret = renameAllIDsAndPrepend("");
  if (ret != LIBSBML_OPERATION_SUCCESS) {
    return ret;
  }

  //Perform replacements and conversions (top-down) and collect them.
  ret = collectRenameAndConvertReplacements(&mRemoved, &toremove);

  if (ret != LIBSBML_OPERATION_SUCCESS) {
    return ret;
  }

  //Finally, actually remove the collected elements from the model--they are
  // all now redundant.  Have to wait until now to do this, because of the
  // possibility of nested constructs:  replacing the child of a replaced
  // element, for example, or even replacing the child of a deleted
  // element.
  removeCollectedElements(&mRemoved, &toremove);

  mRemoved.clear();

  return LIBSBML_OPERATION_SUCCESS;
}
int main(int argc,char** argv)
{
  int retval = 0;
  SBMLNamespaces sbmlns(3,1,"comp",1);

  // create the document
  SBMLDocument *document = new SBMLDocument(&sbmlns);

  //Define the external model definitions
  CompSBMLDocumentPlugin* compdoc
      = static_cast<CompSBMLDocumentPlugin*>(document->getPlugin("comp"));
  compdoc->setRequired(true);
  ExternalModelDefinition* extmod = compdoc->createExternalModelDefinition();
  extmod->setId("ExtMod1");
  extmod->setSource("enzyme_model.xml");
  extmod->setModelRef("enzyme");


  // create the main Model
  Model* model=document->createModel();
  
  // Set the submodels
  CompModelPlugin* mplugin = static_cast<CompModelPlugin*>(model->getPlugin("comp"));
  Submodel* submod1 = mplugin->createSubmodel();
  submod1->setId("A");
  submod1->setModelRef("ExtMod1");
  Submodel* submod2 = mplugin->createSubmodel();
  submod2->setId("B");
  submod2->setModelRef("ExtMod1");

  // create a replacement compartment
  Compartment* comp=model->createCompartment();
  comp->setSpatialDimensions((unsigned int)3);
  comp->setConstant(true);
  comp->setId("comp");
  comp->setSize(1L);

  //Tell the model that this compartment replaces both of the inside ones.
  CompSBasePlugin* compartplug = static_cast<CompSBasePlugin*>(comp->getPlugin("comp"));
  ReplacedElement re;
  re.setIdRef("comp");
  re.setSubmodelRef("A");
  compartplug->addReplacedElement(&re);
  re.setSubmodelRef("B");
  compartplug->addReplacedElement(&re);

  // create a replacement species
  Species* spec = model->createSpecies();
  spec->setCompartment("comp");
  spec->setHasOnlySubstanceUnits(false);
  spec->setConstant(false);
  spec->setBoundaryCondition(false);
  spec->setId("S");

  //Tell the model that this species replaces both of the inside ones.
  CompSBasePlugin* spp = static_cast<CompSBasePlugin*>(spec->getPlugin("comp"));
  re.setIdRef("S");
  re.setSubmodelRef("A");
  spp->addReplacedElement(&re);
  re.setSubmodelRef("B");
  spp->addReplacedElement(&re);

  writeSBMLToFile(document,"eg-import-external.xml");
  writeSBMLToFile(document,"spec_example2.xml");
  delete document;
  document = readSBMLFromFile("spec_example2.xml");
  if (document == NULL)
  {
    cout << "Error reading back in file." << endl;
    retval = -1;
  }
  else
  {
    document->setConsistencyChecks(LIBSBML_CAT_UNITS_CONSISTENCY, false);
    document->checkConsistency();
    if (document->getErrorLog()->getNumFailsWithSeverity(2) > 0
        || document->getErrorLog()->getNumFailsWithSeverity(3) > 0)
    {
      stringstream errorstream;
      document->printErrors(errorstream);
      cout << "Errors encoutered when round-tripping  SBML file: \n"
           <<  errorstream.str() << endl;
      retval = -1;
    }
    writeSBMLToFile(document, "spec_example2_rt.xml");
    delete document;
  }
#ifdef WIN32
  if (retval != 0)
  {
    cout << "(Press any key to exit.)" << endl;
    _getch();
  }
#endif
  return retval;
}
LIBSBML_CPP_NAMESPACE_USE

int main(int argc,char** argv)
{
  
  DynPkgNamespaces sbmlns;
  sbmlns.addPackageNamespace("comp", 1, "comp");

  // create the document

  SBMLDocument *document = new SBMLDocument(&sbmlns);
  document->setPackageRequired("dyn", true);
  document->setPackageRequired("comp", true);

  // create the Model

  Model* model=document->createModel();
  model->setId("grid2x2");

  // create the Compartment

  Compartment* compartment = model->createCompartment();
  compartment->setId("Loc1");
  compartment->setConstant(false);
  compartment->setSize(1);
  compartment->setSpatialDimensions(2.0);

  DynCompartmentPlugin* cplugin =
    static_cast<DynCompartmentPlugin*>(compartment->getPlugin("dyn"));
  
  SpatialComponent* component = cplugin->createSpatialComponent();
  component->setSpatialIndex(DYN_SPATIALKIND_CARTESIANX);
  component->setVariable("q1_X");

  component = cplugin->createSpatialComponent();
  component->setSpatialIndex(DYN_SPATIALKIND_CARTESIANY);
  component->setVariable("q1_Y");

  CompSBasePlugin* compPlugin = 
    static_cast<CompSBasePlugin*>(compartment->getPlugin("comp"));

  ReplacedElement* relement = compPlugin->createReplacedElement();
  relement->setIdRef("C");
  relement->setSubmodelRef("GRID_1_1_cell");

  compartment = model->createCompartment();
  compartment->setId("Loc2");
  compartment->setConstant(false);
  compartment->setSize(1);
  compartment->setSpatialDimensions(2.0);

  cplugin =
    static_cast<DynCompartmentPlugin*>(compartment->getPlugin("dyn"));

  component = cplugin->createSpatialComponent();
  component->setSpatialIndex(DYN_SPATIALKIND_CARTESIANX);
  component->setVariable("q2_X");

  component = cplugin->createSpatialComponent();
  component->setSpatialIndex(DYN_SPATIALKIND_CARTESIANY);
  component->setVariable("q2_Y");

  compPlugin =
    static_cast<CompSBasePlugin*>(compartment->getPlugin("comp"));

  relement = compPlugin->createReplacedElement();
  relement->setIdRef("C");
  relement->setSubmodelRef("GRID_1_2_cell");

  compartment = model->createCompartment();
  compartment->setId("Loc3");
  compartment->setConstant(false);
  compartment->setSize(1);
  compartment->setSpatialDimensions(2.0);

  cplugin =
    static_cast<DynCompartmentPlugin*>(compartment->getPlugin("dyn"));

  component = cplugin->createSpatialComponent();
  component->setSpatialIndex(DYN_SPATIALKIND_CARTESIANX);
  component->setVariable("q3_X");

  component = cplugin->createSpatialComponent();
  component->setSpatialIndex(DYN_SPATIALKIND_CARTESIANY);
  component->setVariable("q3_Y");

  compPlugin =
    static_cast<CompSBasePlugin*>(compartment->getPlugin("comp"));

  relement = compPlugin->createReplacedElement();
  relement->setIdRef("C");
  relement->setSubmodelRef("GRID_2_1_cell");

  compartment = model->createCompartment();
  compartment->setId("Loc4");
  compartment->setConstant(false);
  compartment->setSize(1);
  compartment->setSpatialDimensions(2.0);

  cplugin =
    static_cast<DynCompartmentPlugin*>(compartment->getPlugin("dyn"));

  component = cplugin->createSpatialComponent();
  component->setSpatialIndex(DYN_SPATIALKIND_CARTESIANX);
  component->setVariable("q4_X");

  component = cplugin->createSpatialComponent();
  component->setSpatialIndex(DYN_SPATIALKIND_CARTESIANY);
  component->setVariable("q4_Y");

  compPlugin =
    static_cast<CompSBasePlugin*>(compartment->getPlugin("comp"));

  relement = compPlugin->createReplacedElement();
  relement->setIdRef("C");
  relement->setSubmodelRef("GRID_2_2_cell");

  // create Parameters

  Parameter* param = model->createParameter();
  param->initDefaults();
  param->setId("q1_X");
  param->setValue(1);

  param = model->createParameter();
  param->initDefaults();
  param->setId("q1_Y");
  param->setValue(1);

  param = model->createParameter();
  param->initDefaults();
  param->setId("q2_X");
  param->setValue(2);

  param = model->createParameter();
  param->initDefaults();
  param->setId("q2_Y");
  param->setValue(1);
  
  param = model->createParameter();
  param->initDefaults();
  param->setId("q3_X");
  param->setValue(1);

  param = model->createParameter();
  param->initDefaults();
  param->setId("q3_Y");
  param->setValue(2);

  param = model->createParameter();
  param->initDefaults();
  param->setId("q4_X");
  param->setValue(2);

  param = model->createParameter();
  param->initDefaults();
  param->setId("q4_Y");
  param->setValue(2);

  // create SubModels

  CompModelPlugin* mplugin =
    static_cast<CompModelPlugin*>(model->getPlugin("comp"));

  Submodel* submodel = mplugin->createSubmodel();
  submodel->setId("GRID_1_1_cell");
  submodel->setModelRef("Cell");

  submodel = mplugin->createSubmodel();
  submodel->setId("GRID_1_2_cell");
  submodel->setModelRef("Cell");

  submodel = mplugin->createSubmodel();
  submodel->setId("GRID_2_1_cell");
  submodel->setModelRef("Cell");

  submodel = mplugin->createSubmodel();
  submodel->setId("GRID_2_2_cell");
  submodel->setModelRef("Cell");

  // create the ModelDefinition

  CompSBMLDocumentPlugin* dplugin =
    static_cast<CompSBMLDocumentPlugin*>(document->getPlugin("comp"));
  
  ModelDefinition* mdef = dplugin->createModelDefinition();
  mdef->setId("Cell");

  compartment = mdef->createCompartment();
  compartment->initDefaults();
  compartment->setId("C");
  compartment->setSpatialDimensions(2.0);
  compartment->setSize(1.0);

  Species* species = mdef->createSpecies();
  species->setId("R");
  species->setCompartment("C");
  species->setHasOnlySubstanceUnits(false);
  species->setBoundaryCondition(false);
  species->setConstant(false);

  species = mdef->createSpecies();
  species->setId("S");
  species->setCompartment("C");
  species->setHasOnlySubstanceUnits(false);
  species->setBoundaryCondition(false);
  species->setConstant(false);

  Reaction* reaction = mdef->createReaction();
  reaction->setId("Degradation_R");
  reaction->setReversible(false);
  reaction->setFast(false);
  reaction->setCompartment("C");

  SpeciesReference* reactant = reaction->createReactant();  
  reactant->setSpecies("R");
  reactant->setStoichiometry(1);
  reactant->setConstant(true);
  
  reaction = mdef->createReaction();
  reaction->setId("Degradation_S");
  reaction->setReversible(false);
  reaction->setFast(false);
  reaction->setCompartment("C");

  reactant = reaction->createReactant();
  reactant->setSpecies("S");
  reactant->setStoichiometry(1);
  reactant->setConstant(true);
  document->checkConsistency();

  Event* event = mdef->createEvent();
  event->setId("event0");
  event->setUseValuesFromTriggerTime(false);

  DynEventPlugin* eplugin =
    static_cast<DynEventPlugin*>(event->getPlugin("dyn"));
  eplugin->setApplyToAll(true);
  eplugin->setCboTerm("http://cbo.biocomplexity.indiana.edu/svn/cbo/trunk/CBO_1_0.owl#CellDivision");

  Trigger* trigger = event->createTrigger();
  trigger->setInitialValue(false);
  trigger->setPersistent(false);
  trigger->setMath(SBML_parseFormula("true"));

  if (document->getNumErrors(LIBSBML_SEV_ERROR) > 0)
    document->printErrors();

  writeSBML(document,"dyn_example2.xml");
  delete document;

}
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;
}
int 
CompModelPlugin::renameAllIDsAndPrepend(const std::string& prefix)
{
  SBMLDocument* doc = getSBMLDocument();
  Model* model = static_cast<Model*>(getParentSBMLObject());
  if (model==NULL) {
    if (doc) {
      string error = "Unable to rename elements in CompModelPlugin::renameAllIDsAndPrepend: no parent model could be found for the given 'comp' model plugin element.";
      doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error);
    }
    return LIBSBML_INVALID_OBJECT;
  }

  //First rename the elements in all instantiated submodels.
  vector<string> submodids;

  for (unsigned int sm=0; sm<getNumSubmodels(); sm++) {
    Submodel* subm=getSubmodel(sm);
    if (subm==NULL) {
      if (doc) {
        stringstream error;
        error << "Unable to rename elements in CompModelPlugin::renameAllIDsAndPrepend: no valid submodel number " << sm << "for model " << model->getId();
        doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed,
          getPackageVersion(), getLevel(), getVersion(), error.str());
      }
      return LIBSBML_OPERATION_FAILED;
    }
    if (!subm->isSetId()) {
      if (doc) {
        stringstream error;
        error << "Unable to rename elements in CompModelPlugin::renameAllIDsAndPrepend: submodel number " << sm << "for model " << model->getId() << " is invalid: it has no 'id' attribute set.";
        doc->getErrorLog()->logPackageError("comp", CompSubmodelAllowedAttributes,
          getPackageVersion(), getLevel(), getVersion(), error.str());
      }
      return LIBSBML_INVALID_OBJECT;
    }
    submodids.push_back(subm->getId());
  }

  //Check to see if any of the various submodel ids are used as a prefix 
  List* allElements = model->getAllElements();
  findUniqueSubmodPrefixes(submodids, allElements);

  //Now that we've found valid prefixes for all our submodels, call this function recursively on them.
  for (unsigned int sm=0; sm<getNumSubmodels(); sm++) {
    Submodel* subm=getSubmodel(sm); //already checked this above.
    Model* inst = subm->getInstantiation();
    if (inst==NULL) {
      //'getInstantiation' will set its own error messages.
      delete allElements;
      return LIBSBML_OPERATION_FAILED;
    }
    CompModelPlugin* instp = static_cast<CompModelPlugin*>(inst->getPlugin(getPrefix()));
    if (instp==NULL) {
      if (doc) {
        //Shouldn't happen:  'getInstantiation' turns on the comp plugin.
        string error = "Unable to rename elements in CompModelPlugin::renameAllIDsAndPrepend: no valid 'comp' plugin for the model instantiated from submodel " + subm->getId();
        doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error);
      }
      delete allElements;
      return LIBSBML_OPERATION_FAILED;
    }
    int ret = instp->renameAllIDsAndPrepend(prefix + submodids[sm]);
    if (ret != LIBSBML_OPERATION_SUCCESS) {
      //'renameAllIds..' will set its own error messages.
      delete allElements;
      return ret;
    }
  }

  //Finally, actually rename the elements in *this* model with the prefix.
  if (prefix.empty()) 
  {
    delete allElements;
    return LIBSBML_OPERATION_SUCCESS; //Nothing to add
  }

  //Rename the SIds, UnitSIds, and MetaIDs, and references to them.
  renameIDs(allElements, prefix);
  delete allElements;

  return LIBSBML_OPERATION_SUCCESS;
}
/** @cond doxygenLibsbmlInternal */
int 
CompFlatteningConverter::performConversion()
{  
  int result = LIBSBML_OPERATION_FAILED;

  if (mDocument == NULL) 
  {
    return LIBSBML_INVALID_OBJECT;
  }

  Model* mModel = mDocument->getModel();
  if (mModel == NULL) 
  {
    return LIBSBML_INVALID_OBJECT;
  }

  CompSBMLDocumentPlugin *plugin = 
                  (CompSBMLDocumentPlugin*)(mDocument->getPlugin("comp"));

  // if we don't have a comp model we are done already
  if (plugin == NULL)
  {
    return LIBSBML_OPERATION_SUCCESS;
  }

  // strip packages as instructed by user
  int success = stripPackages();
  if (success != LIBSBML_OPERATION_SUCCESS)
  {
    return LIBSBML_OPERATION_FAILED;
  }

  // look at the document and work out the status of any remaining packages
  mPackageValues.clear();
  analyseDocument();

  bool canFlatten = canBeFlattened();
  

  if (canFlatten == false)
  {
    return LIBSBML_OPERATION_FAILED;
  }

 

  /* strip any unflattenable packages before we run validation */
  if (getStripUnflattenablePackages() == true)
  {
    stripUnflattenablePackages();
  }

  /* run the comp validation rules as flattening will fail
   * if there are bad or missing references between elements
   */

  if (getPerformValidation() == true)
  {
    result = validateOriginalDocument();
    if (result != LIBSBML_OPERATION_SUCCESS) 
    {
      return result;
    }
  }
  CompModelPlugin *modelPlugin = (CompModelPlugin*)(mModel->getPlugin("comp"));

  if (modelPlugin==NULL) 
  {
    restoreNamespaces();
    return LIBSBML_OPERATION_FAILED;
  }

  mDocument->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed,
    modelPlugin->getPackageVersion(), mDocument->getLevel(), 
    mDocument->getVersion(),
    "The subsequent errors are from this attempt.");

  // setup callback that will enable the packages on submodels
  disable_info mainDoc;
  mainDoc.doc = mDocument;
  mainDoc.strippedPkgs = getPackagesToStrip();
  mainDoc.disabledPkgs = mDisabledPackages;
  mainDoc.stripUnflattenable = getStripUnflattenablePackages();
  mainDoc.abortForRequiredOnly = getAbortForRequired(); 
 
  Submodel::addProcessingCallback(&EnablePackageOnParentDocument, &(mainDoc));
  Model* flatmodel = modelPlugin->flattenModel();
  

  if (flatmodel == NULL) 
  {
    //'flattenModel' sets its own error messages.
    restoreNamespaces();
    return LIBSBML_OPERATION_FAILED;
  }

  // we haven't failed flattening so remove that error message
  mDocument->getErrorLog()->remove(CompModelFlatteningFailed);
  

  if (getPerformValidation() == true)
  {
    flatmodel->populateAllElementIdList();
    flatmodel->populateAllElementMetaIdList();
    result = validateFlatDocument(flatmodel,
                    modelPlugin->getPackageVersion(), modelPlugin->getLevel(), 
                    modelPlugin->getVersion());
    if (result != LIBSBML_OPERATION_SUCCESS)
    {
      delete flatmodel;
      return result;
    }
  }

  // now reconstruct the document to be returned 
  // taking user options into account
  result = reconstructDocument(flatmodel);
  delete flatmodel;


  if (result != LIBSBML_OPERATION_SUCCESS) 
  {
    restoreNamespaces();
    return result;
  }

  return LIBSBML_OPERATION_SUCCESS;
}