void createKineticLawForReaction(Reaction* reaction)
{
  if (reaction == NULL)
    return;
  reaction->unsetKineticLaw();
  KineticLaw *law = reaction->getKineticLaw();
  if (law == NULL)
  {
    law = reaction->createKineticLaw();
    LocalParameter* fluxValue = law->createLocalParameter();
    fluxValue->initDefaults();
    fluxValue->setId("FLUX_VALUE");
    fluxValue->setValue(0);
    fluxValue->setUnits("dimensionless");
    ASTNode* astn = SBML_parseFormula("FLUX_VALUE");
    law->setMath(astn);
    delete astn;
  }

  LocalParameter* LB = law->getLocalParameter("LOWER_BOUND");
  if (LB == NULL)
  {
    LB = law->createLocalParameter();
    LB->initDefaults();
    LB->setId("LOWER_BOUND");
    LB->setUnits("dimensionless");
    LB->setValue(-std::numeric_limits<double>::infinity());
  }

  LocalParameter* UB = law->getLocalParameter("UPPER_BOUND");
  if (UB == NULL)
  {
    UB = law->createLocalParameter();
    UB->initDefaults();
    UB->setId("UPPER_BOUND");
    UB->setUnits("dimensionless");
    LB->setValue(std::numeric_limits<double>::infinity());
  }

  LocalParameter* param = law->getLocalParameter("OBJECTIVE_COEFFICIENT");
  if (param == NULL)
  {
    param = law->createLocalParameter();
    param->initDefaults();
    param->setId("OBJECTIVE_COEFFICIENT");
    param->setUnits("dimensionless");
    param->setValue(0);
  }

}
END_TEST

START_TEST ( test_KineticLaw )
{
  KineticLaw* kl = new KineticLaw(2, 4);
   
  fail_unless (!(kl->hasRequiredElements()));

  kl->setMath(SBML_parseFormula("kl"));

  fail_unless (kl->hasRequiredElements());

  delete kl;
}
void 
convertPow(SBMLDocument* doc, 
           bool shouldChangePow, 
           bool inlineCompartmentSizes)
{

  Model* model = SBMLDocument_getModel(doc);
  if (model == NULL)
  {
    return;
  }

  std::map<string, double> compartmentValueMap;
  if (inlineCompartmentSizes)
  {
    for(unsigned int i = 0; i < model->getNumCompartments(); ++i)
    {
      Compartment* c = model->getCompartment(i);
      compartmentValueMap[c->getId()] = c->getSize();
    }
  }

  for(unsigned int i = 0; i < model->getNumReactions(); ++i)
  {
    Reaction* r  = model->getReaction(i);
    KineticLaw* kl = r->getKineticLaw();
    const char* strKineticFormula;
    if (kl == NULL)
    {
      strKineticFormula = "";
    }
    else
    {
      strKineticFormula = KineticLaw_getFormula(kl);
      if (strKineticFormula == NULL)
      {
        continue;
      }
    }

    ASTNode* ast_Node	= SBML_parseFormula (strKineticFormula);
    if (ast_Node != NULL)
    {
      changePow(ast_Node, compartmentValueMap, shouldChangePow);
      kl->setMath (ast_Node);
    }
    delete ast_Node;
  }
}
/**
 *
 * Creates an SBML model represented in "7.2 Example involving units"
 * in the SBML Level 2 Version 4 Specification.
 *
 */
SBMLDocument* createExampleInvolvingUnits()
{
  const unsigned int level   = Level;
  const unsigned int version = Version;

  //---------------------------------------------------------------------------
  //
  // Creates an SBMLDocument object 
  //
  //---------------------------------------------------------------------------

  SBMLDocument* sbmlDoc = new SBMLDocument(level,version);

  // Adds the namespace for XHTML to the SBMLDocument object.  We need this
  // because we will add notes to the model.  (By default, the SBML document
  // created by SBMLDocument only declares the SBML XML namespace.)

  sbmlDoc->getNamespaces()->add("http://www.w3.org/1999/xhtml", "xhtml");

  //---------------------------------------------------------------------------
  //
  // Creates a Model object inside the SBMLDocument object. 
  //
  //---------------------------------------------------------------------------

  Model* model = sbmlDoc->createModel();
  model->setId("unitsExample");

  //---------------------------------------------------------------------------
  //
  // Creates UnitDefinition objects inside the Model object.
  //
  //---------------------------------------------------------------------------

  // Temporary pointers (reused more than once below).

  UnitDefinition* unitdef;
  Unit *unit;

  //---------------------------------------------------------------------------  
  // (UnitDefinition1) Creates an UnitDefinition object ("substance").
  //
  // This has the effect of redefining the default unit of subtance for the
  // whole model.
  //---------------------------------------------------------------------------

  unitdef = model->createUnitDefinition();
  unitdef->setId("substance");

  //  Creates an Unit inside the UnitDefinition object 

  unit = unitdef->createUnit();
  unit->setKind(UNIT_KIND_MOLE);
  unit->setScale(-3);

  //--------------------------------------------------------------------------------
  // (UnitDefinition2) Creates an UnitDefinition object ("mmls") 
  //--------------------------------------------------------------------------------
    
  // Note that we can reuse the pointers 'unitdef' and 'unit' because the
  // actual UnitDefinition object (along with the Unit objects within it)
  // is already attached to the Model object.

  unitdef = model->createUnitDefinition();
  unitdef->setId("mmls");
    
  //  Creates an Unit inside the UnitDefinition object ("mmls")

  unit = unitdef->createUnit();
  unit->setKind(UNIT_KIND_MOLE);
  unit->setScale(-3);

  //  Creates an Unit inside the UnitDefinition object ("mmls")

  unit = unitdef->createUnit();
  unit->setKind(UNIT_KIND_LITRE);
  unit->setExponent(-1);

  //  Creates an Unit inside the UnitDefinition object ("mmls")

  unit = unitdef->createUnit();
  unit->setKind(UNIT_KIND_SECOND);
  unit->setExponent(-1);

  //--------------------------------------------------------------------------------
  // (UnitDefinition3) Creates an UnitDefinition object ("mml") 
  //--------------------------------------------------------------------------------
    
  unitdef = model->createUnitDefinition();
  unitdef->setId("mml");
    
  //  Creates an Unit inside the UnitDefinition object ("mml")

  unit = unitdef->createUnit();
  unit->setKind(UNIT_KIND_MOLE);
  unit->setScale(-3);

  //  Creates an Unit inside the UnitDefinition object ("mml")

  unit = unitdef->createUnit();
  unit->setKind(UNIT_KIND_LITRE);
  unit->setExponent(-1);


  //---------------------------------------------------------------------------
  //
  // Creates a Compartment object inside the Model object. 
  //
  //---------------------------------------------------------------------------

  Compartment* comp;
  const string compName = "cell";

  // Creates a Compartment object ("cell")

  comp = model->createCompartment();
  comp->setId(compName);
 
  // Sets the "size" attribute of the Compartment object.
  //
  //   The units of this Compartment object is the default SBML 
  //   units of volume (litre), and thus we don't have to explicitly invoke 
  //   setUnits("litre") function to set the default units.
  //
  comp->setSize(1);


  //---------------------------------------------------------------------------
  //
  // Creates Species objects inside the Model object. 
  //
  //---------------------------------------------------------------------------
  
  // Temporary pointer (reused more than once below).
  
  Species *sp;

  //---------------------------------------------------------------------------
  // (Species1) Creates a Species object ("x0")
  //---------------------------------------------------------------------------

  sp = model->createSpecies();
  sp->setId("x0");

  // Sets the "compartment" attribute of the Species object to identify the 
  // compartnet in which the Species object located.

  sp->setCompartment(compName);

  // Sets the "initialConcentration" attribute of the Species object.
  //
  //  The units of this Species object is determined by two attributes of this 
  //  Species object ("substanceUnits" and "hasOnlySubstanceUnits") and the
  //  "spatialDimensions" attribute of the Compartment object ("cytosol") in which 
  //  this species object is located.
  //  Since the default values are used for "substanceUnits" (substance (mole)) 
  //  and "hasOnlySubstanceUnits" (false) and the value of "spatialDimension" (3) 
  //  is greater than 0, the units of this Species object is  moles/liters . 
  //
  sp->setInitialConcentration(1);

  //---------------------------------------------------------------------------
  // (Species2) Creates a Species object ("x1")
  //---------------------------------------------------------------------------

  sp = model->createSpecies();
  sp->setId("x1");
  sp->setCompartment(compName);
  sp->setInitialConcentration(1);

  //---------------------------------------------------------------------------
  // (Species3) Creates a Species object ("s1")
  //---------------------------------------------------------------------------

  sp = model->createSpecies();
  sp->setCompartment(compName);
  sp->setId("s1");
  sp->setInitialConcentration(1);

  //---------------------------------------------------------------------------
  // (Species4) Creates a Species object ("s2")
  //---------------------------------------------------------------------------

  sp = model->createSpecies();
  sp->setCompartment(compName);
  sp->setId("s2");
  sp->setInitialConcentration(1);

  //---------------------------------------------------------------------------
  //
  // Creates global Parameter objects inside the Model object. 
  //
  //---------------------------------------------------------------------------

  Parameter* para;

  // Creates a Parameter ("vm")  

  para = model->createParameter();
  para->setId("vm");
  para->setValue(2);
  para->setUnits("mmls");

  // Creates a Parameter ("km")  

  para = model->createParameter();
  para->setId("km");
  para->setValue(2);
  para->setUnits("mml");


  //---------------------------------------------------------------------------
  //
  // Creates Reaction objects inside the Model object. 
  //
  //---------------------------------------------------------------------------
  
  // Temporary pointers.

  Reaction* reaction;
  SpeciesReference* spr;
  KineticLaw* kl;

  //---------------------------------------------------------------------------
  // (Reaction1) Creates a Reaction object ("v1").
  //---------------------------------------------------------------------------

  reaction = model->createReaction();
  reaction->setId("v1");

  //---------------------------------------------------------------------------
  // Creates Reactant objects inside the Reaction object ("v1"). 
  //---------------------------------------------------------------------------

  // (Reactant1) Creates a Reactant object that references Species "x0"
  // in the model.

  spr = reaction->createReactant();
  spr->setSpecies("x0");

  //---------------------------------------------------------------------------
  // Creates a Product object inside the Reaction object ("v1"). 
  //---------------------------------------------------------------------------

  // Creates a Product object that references Species "s1" in the model. 

  spr = reaction->createProduct();
  spr->setSpecies("s1");

  //---------------------------------------------------------------------------
  // Creates a KineticLaw object inside the Reaction object ("v1"). 
  //---------------------------------------------------------------------------
  
  kl = reaction->createKineticLaw();

  // Creates a <notes> element in the KineticLaw object.
  // Here we illustrate how to do it using a literal string.  This requires
  // known the required syntax of XHTML and the requirements for SBML <notes>
  // elements.  Later below, we show how to create notes using objects instead
  // of strings.

  string notesString = "<xhtml:p> ((vm * s1)/(km + s1)) * cell </xhtml:p>";
  kl->setNotes(notesString);

  //---------------------------------------------------------------------------
  // Creates an ASTNode object which represents the following KineticLaw object.
  //
  //  <math xmlns=\"http://www.w3.org/1998/Math/MathML\">
  //   <apply>
  //     <times/>
  //     <apply>
  //       <divide/>
  //       <apply>
  //         <times/>
  //           <ci> vm </ci>
  //           <ci> s1 </ci>
  //       </apply>
  //       <apply>
  //         <plus/>
  //           <ci> km </ci>
  //           <ci> s1 </ci>
  //       </apply>
  //     </apply>
  //     <ci> cell </ci>
  //    </apply>
  //  </math>
  //---------------------------------------------------------------------------

  //
  // In the following code, ASTNode objects, which construct an ASTNode tree 
  // of the above math, are created and added in the order of preorder traversal 
  // of the tree (i.e. the order corresponds to the nested structure of the above 
  // MathML elements), and thus the following code maybe a bit more efficient but 
  // maybe a bit difficult to read.
  //

  ASTNode* astMath = new ASTNode(AST_TIMES);

  astMath->addChild(new ASTNode(AST_DIVIDE));
  ASTNode* astDivide = astMath->getLeftChild();

  astDivide->addChild(new ASTNode(AST_TIMES));
  ASTNode* astTimes = astDivide->getLeftChild();

  astTimes->addChild(new ASTNode(AST_NAME));
  astTimes->getLeftChild()->setName("vm");

  astTimes->addChild(new ASTNode(AST_NAME));
  astTimes->getRightChild()->setName("s1");

  astDivide->addChild(new ASTNode(AST_PLUS));
  ASTNode* astPlus = astDivide->getRightChild();

  astPlus->addChild(new ASTNode(AST_NAME));
  astPlus->getLeftChild()->setName("km");

  astPlus->addChild(new ASTNode(AST_NAME));
  astPlus->getRightChild()->setName("s1");


  astMath->addChild(new ASTNode(AST_NAME));
  astMath->getRightChild()->setName("cell");

  //---------------------------------------------
  //
  // set the Math element
  //
  //------------------------------------------------

  kl->setMath(astMath);
  delete astMath;


  //---------------------------------------------------------------------------
  // (Reaction2) Creates a Reaction object ("v2").
  //---------------------------------------------------------------------------

  reaction = model->createReaction();
  reaction->setId("v2");

  //---------------------------------------------------------------------------
  // Creates Reactant objects inside the Reaction object ("v2"). 
  //---------------------------------------------------------------------------

  // (Reactant2) Creates a Reactant object that references Species "s1"
  // in the model.

  spr = reaction->createReactant();
  spr->setSpecies("s1");

  //---------------------------------------------------------------------------
  // Creates a Product object inside the Reaction object ("v2"). 
  //---------------------------------------------------------------------------

  // Creates a Product object that references Species "s2" in the model. 

  spr = reaction->createProduct();
  spr->setSpecies("s2");

  //---------------------------------------------------------------------------
  // Creates a KineticLaw object inside the Reaction object ("v2"). 
  //---------------------------------------------------------------------------
  
  kl = reaction->createKineticLaw();

  // Sets a notes (by XMLNode) to the KineticLaw object.
  //
  // The following code is an alternative to using setNotes(const string&).
  // The equivalent code would be like this:
  //   
  //     notesString = "<xhtml:p>((vm * s2)/(km + s2))*cell</xhtml:p>";
  //     kl->setNotes(notesString);

  // Creates an XMLNode of start element (<xhtml:p>) without attributes.

  XMLNode notesXMLNode(XMLTriple("p", "", "xhtml"), XMLAttributes());

  // Adds a text element to the start element.

  notesXMLNode.addChild(XMLNode(" ((vm * s2)/(km + s2)) * cell ")); 

  // Adds it to the kineticLaw object.

  kl->setNotes(&notesXMLNode);

  //---------------------------------------------------------------------------
  // Sets a math (ASTNode object) to the KineticLaw object.
  //---------------------------------------------------------------------------

  // To create mathematical expressions, one would typically construct
  // an ASTNode tree as the above example code which creates a math of another
  // KineticLaw object.  Here, to save some space and illustrate another approach 
  // of doing it, we will write out the formula in MathML form and then use a 
  // libSBML convenience function to create the ASTNode tree for us.  
  // (This is a bit dangerous; it's very easy to make mistakes when writing MathML 
  // by hand, so in a real program, we would not really want to do it this way.)

  string mathXMLString = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"
                         "  <apply>"
                         "    <times/>"
                         "    <apply>"
                         "      <divide/>"
                         "      <apply>"
                         "        <times/>"
                         "        <ci> vm </ci>"
                         "        <ci> s2 </ci>"
                         "      </apply>"
                         "      <apply>"
                         "        <plus/>"
                         "          <ci> km </ci>"
                         "          <ci> s2 </ci>"
                         "      </apply>"
                         "    </apply>"
                         "    <ci> cell </ci>"
                         "  </apply>"
                         "</math>";

  astMath = readMathMLFromString(mathXMLString.c_str());
  kl->setMath(astMath);
  delete astMath;


  //---------------------------------------------------------------------------
  // (Reaction3) Creates a Reaction object ("v3").
  //---------------------------------------------------------------------------

  reaction = model->createReaction();
  reaction->setId("v3");

  //---------------------------------------------------------------------------
  // Creates Reactant objects inside the Reaction object ("v3"). 
  //---------------------------------------------------------------------------

  // (Reactant2) Creates a Reactant object that references Species "s2"
  // in the model.

  spr = reaction->createReactant();
  spr->setSpecies("s2");

  //---------------------------------------------------------------------------
  // Creates a Product object inside the Reaction object ("v3"). 
  //---------------------------------------------------------------------------

  // Creates a Product object that references Species "x1" in the model. 

  spr = reaction->createProduct();
  spr->setSpecies("x1");


  //---------------------------------------------------------------------------
  // Creates a KineticLaw object inside the Reaction object ("v3"). 
  //---------------------------------------------------------------------------
  
  kl = reaction->createKineticLaw();

  // Sets a notes (by string) to the KineticLaw object.

  notesString = "<xhtml:p> ((vm * x1)/(km + x1)) * cell </xhtml:p>";
  kl->setNotes(notesString);

  //---------------------------------------------------------------------------
  // Sets a math (ASTNode object) to the KineticLaw object.
  //---------------------------------------------------------------------------

  mathXMLString = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"
                  "  <apply>"
                  "    <times/>"
                  "    <apply>"
                  "      <divide/>"
                  "      <apply>"
                  "        <times/>"
                  "        <ci> vm </ci>"
                  "        <ci> x1 </ci>"
                  "      </apply>"
                  "      <apply>"
                  "        <plus/>"
                  "          <ci> km </ci>"
                  "          <ci> x1 </ci>"
                  "      </apply>"
                  "    </apply>"
                  "    <ci> cell </ci>"
                  "  </apply>"
                  "</math>";

  astMath = readMathMLFromString(mathXMLString.c_str());
  kl->setMath(astMath);
  delete astMath;


  // Returns the created SBMLDocument object.
  // The returned object must be explicitly deleted by the caller,
  // otherwise memory leak will happen.

  return sbmlDoc;

}
/**
 *
 * Creates an SBML model represented in "7.1 A Simple example application of SBML"
 * in the SBML Level 2 Version 4 Specification.
 *
 */
SBMLDocument* createExampleEnzymaticReaction()
{
  const unsigned int level   = Level;
  const unsigned int version = Version;

  //---------------------------------------------------------------------------
  //
  // Creates an SBMLDocument object 
  //
  //---------------------------------------------------------------------------

  SBMLDocument* sbmlDoc = new SBMLDocument(level,version);

  //---------------------------------------------------------------------------
  //
  // Creates a Model object inside the SBMLDocument object. 
  //
  //---------------------------------------------------------------------------

  Model* model = sbmlDoc->createModel();
  model->setId("EnzymaticReaction");

  //---------------------------------------------------------------------------
  //
  // Creates UnitDefinition objects inside the Model object.
  //
  //---------------------------------------------------------------------------

  // Temporary pointers (reused more than once below).

  UnitDefinition* unitdef;
  Unit* unit;

  //---------------------------------------------------------------------------  
  // (UnitDefinition1) Creates an UnitDefinition object ("per_second")
  //---------------------------------------------------------------------------

  unitdef = model->createUnitDefinition();
  unitdef->setId("per_second");

  //  Creates an Unit inside the UnitDefinition object 

  unit = unitdef->createUnit();
  unit->setKind(UNIT_KIND_SECOND);
  unit->setExponent(-1);

  //--------------------------------------------------------------------------------
  // (UnitDefinition2) Creates an UnitDefinition object ("litre_per_mole_per_second") 
  //--------------------------------------------------------------------------------
    
  // Note that we can reuse the pointers 'unitdef' and 'unit' because the
  // actual UnitDefinition object (along with the Unit objects within it)
  // is already attached to the Model object.

  unitdef = model->createUnitDefinition();
  unitdef->setId("litre_per_mole_per_second");
    
  //  Creates an Unit inside the UnitDefinition object ("litre_per_mole_per_second")

  unit = unitdef->createUnit();
  unit->setKind(UNIT_KIND_MOLE);
  unit->setExponent(-1);

  //  Creates an Unit inside the UnitDefinition object ("litre_per_mole_per_second")

  unit = unitdef->createUnit();
  unit->setKind(UNIT_KIND_LITRE);
  unit->setExponent(1);

  //  Creates an Unit inside the UnitDefinition object ("litre_per_mole_per_second")

  unit = unitdef->createUnit();
  unit->setKind(UNIT_KIND_SECOND);
  unit->setExponent(-1);


  //---------------------------------------------------------------------------
  //
  // Creates a Compartment object inside the Model object. 
  //
  //---------------------------------------------------------------------------

  Compartment* comp;
  const string compName = "cytosol";

  // Creates a Compartment object ("cytosol")

  comp = model->createCompartment();
  comp->setId(compName);
 
  // Sets the "size" attribute of the Compartment object.
  //
  // We are not setting the units on the compartment size explicitly, so
  // the units of this Compartment object will be the default SBML units of
  // volume, which are liters.
  //
  comp->setSize(1e-14);


  //---------------------------------------------------------------------------
  //
  // Creates Species objects inside the Model object. 
  //
  //---------------------------------------------------------------------------
  
  // Temporary pointer (reused more than once below).
  
  Species *sp;

  //---------------------------------------------------------------------------
  // (Species1) Creates a Species object ("ES")
  //---------------------------------------------------------------------------

  // Create the Species objects inside the Model object. 

  sp = model->createSpecies();
  sp->setId("ES");
  sp->setName("ES");

  // Sets the "compartment" attribute of the Species object to identify the 
  // compartment in which the Species object is located.

  sp->setCompartment(compName);

  // Sets the "initialAmount" attribute of the Species object.
  //
  //  In SBML, the units of a Species object's initial quantity are
  //  determined by two attributes, "substanceUnits" and
  //  "hasOnlySubstanceUnits", and the "spatialDimensions" attribute
  //  of the Compartment object ("cytosol") in which the species
  //  object is located.  Here, we are using the default values for
  //  "substanceUnits" (which is "mole") and "hasOnlySubstanceUnits"
  //  (which is "false").  The compartment in which the species is
  //  located uses volume units of liters, so the units of these
  //  species (when the species appear in numerical formulas in the
  //  model) will be moles/liters.  
  //
  sp->setInitialAmount(0);

  //---------------------------------------------------------------------------
  // (Species2) Creates a Species object ("P")
  //---------------------------------------------------------------------------

  sp = model->createSpecies();
  sp->setCompartment(compName);
  sp->setId("P");
  sp->setName("P");
  sp->setInitialAmount(0);

  //---------------------------------------------------------------------------
  // (Species3) Creates a Species object ("S")
  //---------------------------------------------------------------------------

  sp = model->createSpecies();
  sp->setCompartment(compName);
  sp->setId("S");
  sp->setName("S");
  sp->setInitialAmount(1e-20);

  //---------------------------------------------------------------------------
  // (Species4) Creates a Species object ("E")
  //---------------------------------------------------------------------------

  sp = model->createSpecies();
  sp->setCompartment(compName);
  sp->setId("E");
  sp->setName("E");
  sp->setInitialAmount(5e-21);

  
  //---------------------------------------------------------------------------
  //
  // Creates Reaction objects inside the Model object. 
  //
  //---------------------------------------------------------------------------
  
  // Temporary pointers.

  Reaction* reaction;
  SpeciesReference* spr;
  KineticLaw* kl;

  //---------------------------------------------------------------------------
  // (Reaction1) Creates a Reaction object ("veq").
  //---------------------------------------------------------------------------

  reaction = model->createReaction();
  reaction->setId("veq");

  // (Reactant1) Creates a Reactant object that references Species "E"
  // in the model.  The object will be created within the reaction in the
  // SBML <listOfReactants>.

  spr = reaction->createReactant();
  spr->setSpecies("E");

  // (Reactant2) Creates a Reactant object that references Species "S"
  // in the model.

  spr = reaction->createReactant();
  spr->setSpecies("S");

  //---------------------------------------------------------------------------
  // (Product1) Creates a Product object that references Species "ES" in
  // the model.
  //---------------------------------------------------------------------------

  spr = reaction->createProduct();
  spr->setSpecies("ES");

  //---------------------------------------------------------------------------
  // Creates a KineticLaw object inside the Reaction object ("veq"). 
  //---------------------------------------------------------------------------

  kl = reaction->createKineticLaw();

 //---------------------------------------------------------------------------
   // Creates an ASTNode object which represents the following math of the
   // KineticLaw.
   //
   //      <math xmlns="http://www.w3.org/1998/Math/MathML">
   //        <apply>
   //          <times/>
   //          <ci> cytosol </ci>
   //          <apply>
   //            <minus/>
   //            <apply>
   //              <times/>
   //              <ci> kon </ci>
   //              <ci> E </ci>
   //              <ci> S </ci>
   //            </apply>
   //            <apply>
   //              <times/>
   //              <ci> koff </ci>
   //              <ci> ES </ci>
   //            </apply>
   //          </apply>
   //        </apply>
   //      </math>
   //
 //---------------------------------------------------------------------------

   //------------------------------------------
   //
   // create nodes representing the variables
   //
   //------------------------------------------

   ASTNode* astCytosol = new ASTNode(AST_NAME);
   astCytosol->setName("cytosol");

   ASTNode* astKon = new ASTNode(AST_NAME);
   astKon->setName("kon");

   ASTNode* astKoff = new ASTNode(AST_NAME);
   astKoff->setName("koff");

   ASTNode* astE = new ASTNode(AST_NAME);
   astE->setName("E");

   ASTNode* astS = new ASTNode(AST_NAME);
   astS->setName("S");

   ASTNode* astES = new ASTNode(AST_NAME);
   astES->setName("ES");


   //--------------------------------------------
   //
   // create node representing
   //            <apply>
   //              <times/>
   //              <ci> koff </ci>
   //              <ci> ES </ci>
   //            </apply>
   //
   //--------------------------------------------

   ASTNode *astTimes1 = new ASTNode(AST_TIMES);
   astTimes1->addChild(astKoff);
   astTimes1->addChild(astES);

   //--------------------------------------------
   //
   // create node representing
   //            <apply>
   //              <times/>
   //              <ci> kon </ci>
   //              <ci> E </ci>
   //              <ci> S </ci>
   //            </apply>
   //
   //
   // (NOTES)
   //
   //  Since there is a restriction with an ASTNode of "<times/>" operation
   //  such that the ASTNode is a binary class and thus only two operands can
   //  be directly added, the following code in this comment block is invalid
   //  because the code directly adds three <ci> ASTNodes to <times/> ASTNode.
   //
   //    ASTNode *astTimes = new ASTNode(AST_TIMES);
   //    astTimes->addChild(astKon);
   //    astTimes->addChild(astE);
   //    astTimes->addChild(astS);
   //
   // The following valid code after this comment block creates the ASTNode
   // as a binary tree.
   //
   // Please see "Converting between ASTs and text strings" described
   // at http://sbml.org/Software/libSBML/docs/cpp-api/class_a_s_t_node.html
   // for the detailed information.
   //
   //--------------------------------------------

   ASTNode *astTimes2 = new ASTNode(AST_TIMES);
   astTimes2->addChild(astE);
   astTimes2->addChild(astS);

   ASTNode *astTimes = new ASTNode(AST_TIMES);
   astTimes->addChild(astKon);
   astTimes->addChild(astTimes2);

   //--------------------------------------------
   //
   // create node representing
   //          <apply>
   //            <minus/>
   //            <apply>
   //              <times/>
   //              <ci> kon </ci>
   //              <ci> E </ci>
   //              <ci> S </ci>
   //            </apply>
   //            <apply>
   //              <times/>
   //              <ci> koff </ci>
   //              <ci> ES </ci>
   //            </apply>
   //          </apply>
   //
   //--------------------------------------------

   ASTNode *astMinus = new ASTNode(AST_MINUS);
   astMinus->addChild(astTimes);
   astMinus->addChild(astTimes1);


   //--------------------------------------------
   //
   // create node representing
   //        <apply>
   //          <times/>
   //          <ci> cytosol </ci>
   //          <apply>
   //            <minus/>
   //            <apply>
   //              <times/>
   //              <ci> kon </ci>
   //              <ci> E </ci>
   //              <ci> S </ci>
   //            </apply>
   //            <apply>
   //              <times/>
   //              <ci> koff </ci>
   //              <ci> ES </ci>
   //            </apply>
   //          </apply>
   //        </apply>
   //
   //--------------------------------------------

   ASTNode* astMath = new ASTNode(AST_TIMES);
   astMath->addChild(astCytosol);
   astMath->addChild(astMinus);

   //---------------------------------------------
   //
   // set the Math element
   //
   //------------------------------------------------

   kl->setMath(astMath);

  // KineticLaw::setMath(const ASTNode*) sets the math of the KineticLaw object
  // to a copy of the given ASTNode, and thus basically the caller should delete 
  // the original ASTNode object if the caller has the ownership of the object to 
  // avoid memory leak.

   delete astMath;


  //---------------------------------------------------------------------------
  // Creates local Parameter objects inside the KineticLaw object.
  //---------------------------------------------------------------------------

  // Creates a Parameter ("kon")

  Parameter* para = kl->createParameter();
  para->setId("kon");
  para->setValue(1000000);
  para->setUnits("litre_per_mole_per_second");

  // Creates a Parameter ("koff")

  para = kl->createParameter();
  para->setId("koff");
  para->setValue(0.2);
  para->setUnits("per_second");


  //---------------------------------------------------------------------------
  // (Reaction2) Creates a Reaction object ("vcat") .
  //---------------------------------------------------------------------------
  
  reaction = model->createReaction();
  reaction->setId("vcat");
  reaction->setReversible(false);

  //---------------------------------------------------------------------------
  // Creates Reactant objects inside the Reaction object ("vcat"). 
  //---------------------------------------------------------------------------

  // (Reactant1) Creates a Reactant object that references Species "ES" in the
  // model.

  spr = reaction->createReactant();
  spr->setSpecies("ES");

  //---------------------------------------------------------------------------
  // Creates a Product object inside the Reaction object ("vcat"). 
  //---------------------------------------------------------------------------
  
  // (Product1) Creates a Product object that references Species "E" in the model.

  spr = reaction->createProduct();
  spr->setSpecies("E");

  // (Product2) Creates a Product object that references Species "P" in the model.

  spr = reaction->createProduct();
  spr->setSpecies("P");

  //---------------------------------------------------------------------------
  // Creates a KineticLaw object inside the Reaction object ("vcat"). 
  //---------------------------------------------------------------------------
  
  kl = reaction->createKineticLaw();

  //---------------------------------------------------------------------------
  // Sets a math (ASTNode object) to the KineticLaw object.
  //---------------------------------------------------------------------------

  // To create mathematical expressions, one would typically construct
  // an ASTNode tree as the above example code which creates a math of another
  // KineticLaw object.  Here, to save some space and illustrate another approach 
  // of doing it, we will write out the formula in MathML form and then use a 
  // libSBML convenience function to create the ASTNode tree for us.  
  // (This is a bit dangerous; it's very easy to make mistakes when writing MathML 
  // by hand, so in a real program, we would not really want to do it this way.)

  string mathXMLString = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"
                         "  <apply>"
                         "    <times/>"
                         "    <ci> cytosol </ci>"
                         "    <ci> kcat </ci>"
                         "    <ci> ES </ci>"
                         "  </apply>"
                         "</math>";

  astMath = readMathMLFromString(mathXMLString.c_str());
  kl->setMath(astMath);
  delete astMath;

  //---------------------------------------------------------------------------
  // Creates local Parameter objects inside the KineticLaw object.
  //---------------------------------------------------------------------------

  // Creates a Parameter ("kcat")

  para = kl->createParameter();
  para->setId("kcat");
  para->setValue(0.1);
  para->setUnits("per_second");


  // Returns the created SBMLDocument object.
  // The returned object must be explicitly deleted by the caller,
  // otherwise a memory leak will happen.

  return sbmlDoc;

}
/**
 *
 * Creates an SBML model represented in "7.8 Example involving function definitions"
 * in the SBML Level 2 Version 4 Specification.
 *
 */
SBMLDocument* createExampleInvolvingFunctionDefinitions()
{
  const unsigned int level   = Level;
  const unsigned int version = Version;

  //---------------------------------------------------------------------------
  //
  // Creates an SBMLDocument object 
  //
  //---------------------------------------------------------------------------

  SBMLDocument* sbmlDoc = new SBMLDocument(level,version);

  //---------------------------------------------------------------------------
  //
  // Creates a Model object inside the SBMLDocument object. 
  //
  //---------------------------------------------------------------------------

  Model* model = sbmlDoc->createModel();
  model->setId("functionExample");

  //---------------------------------------------------------------------------
  //
  // Creates a FunctionDefinition object inside the Model object. 
  //
  //---------------------------------------------------------------------------

  FunctionDefinition* fdef = model->createFunctionDefinition();
  fdef->setId("f");

  // Sets a math (ASTNode object) to the FunctionDefinition object.

  string mathXMLString = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"
                         "  <lambda>"
                         "    <bvar>"
                         "      <ci> x </ci>"
                         "    </bvar>"
                         "    <apply>"
                         "      <times/>"
                         "      <ci> x </ci>"
                         "      <cn> 2 </cn>"
                         "    </apply>"
                         "  </lambda>"
                         "</math>";

  ASTNode* astMath = readMathMLFromString(mathXMLString.c_str());
  fdef->setMath(astMath);
  delete astMath;


  //---------------------------------------------------------------------------
  //
  // Creates a Compartment object inside the Model object. 
  //
  //---------------------------------------------------------------------------

  Compartment* comp;
  const string compName = "compartmentOne";

  // Creates a Compartment object ("compartmentOne")

  comp = model->createCompartment();
  comp->setId(compName);
 
  // Sets the "size" attribute of the Compartment object.
  //
  //   The units of this Compartment object is the default SBML 
  //   units of volume (litre), and thus we don't have to explicitly invoke 
  //   setUnits("litre") function to set the default units.
  //
  comp->setSize(1);


  //---------------------------------------------------------------------------
  //
  // Creates Species objects inside the Model object. 
  //
  //---------------------------------------------------------------------------
  
  Species* sp;

  //---------------------------------------------------------------------------
  // (Species1) Creates a Species object ("S1")
  //---------------------------------------------------------------------------

  sp = model->createSpecies();
  sp->setId("S1");

  // Sets the "compartment" attribute of the Species object to identify the 
  // compartnet in which the Species object located.

  sp->setCompartment(compName);

  // Sets the "initialConcentration" attribute of the Species object.
  //
  //  The units of this Species object is determined by two attributes of this 
  //  Species object ("substanceUnits" and "hasOnlySubstanceUnits") and the
  //  "spatialDimension" attribute of the Compartment object ("cytosol") in which 
  //  this species object located.
  //  Since the default values are used for "substanceUnits" (substance (mole)) 
  //  and "hasOnlySubstanceUnits" (false) and the value of "spatialDimension" (3) 
  //  is greater than 0, the units of this Species object is  mole/litre . 
  //

  sp->setInitialConcentration(1);

  //---------------------------------------------------------------------------
  // (Species2) Creates a Species object ("S2")
  //---------------------------------------------------------------------------

  sp = model->createSpecies();
  sp->setId("S2");
  sp->setCompartment(compName);
  sp->setInitialConcentration(0);


  //---------------------------------------------------------------------------
  //
  // Creates a global Parameter object inside the Model object. 
  //
  //---------------------------------------------------------------------------

  Parameter* para;

  // Creates a Parameter ("t")  

  para = model->createParameter();
  para->setId("t");
  para->setValue(1);
  para->setUnits("second");


  //---------------------------------------------------------------------------
  //
  // Creates Reaction objects inside the Model object. 
  //
  //---------------------------------------------------------------------------
  
  // Temporary pointers.

  Reaction* reaction;
  SpeciesReference* spr;
  KineticLaw* kl;

  //---------------------------------------------------------------------------
  // (Reaction1) Creates a Reaction object ("reaction_1").
  //---------------------------------------------------------------------------

  reaction = model->createReaction();
  reaction->setId("reaction_1");
  reaction->setReversible(false);

  //---------------------------------------------------------------------------
  // Creates Reactant objects inside the Reaction object ("reaction_1"). 
  //---------------------------------------------------------------------------

  // (Reactant1) Creates a Reactant object that references Species "S1"
  // in the model.

  spr = reaction->createReactant();
  spr->setSpecies("S1");

  //---------------------------------------------------------------------------
  // Creates a Product object inside the Reaction object ("reaction_1"). 
  //---------------------------------------------------------------------------

  // Creates a Product object that references Species "S2" in the model. 

  spr = reaction->createProduct();
  spr->setSpecies("S2");


  //---------------------------------------------------------------------------
  // Creates a KineticLaw object inside the Reaction object ("reaction_1"). 
  //---------------------------------------------------------------------------
  
  kl = reaction->createKineticLaw();

  //---------------------------------------------------------------------------
  // Sets a math (ASTNode object) to the KineticLaw object.
  //---------------------------------------------------------------------------

  mathXMLString = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"
                  "  <apply>"
                  "  <divide/>"
                  "    <apply>"
                  "      <times/>"
                  "      <apply>"
                  "        <ci> f </ci>"
                  "        <ci> S1 </ci>"
                  "      </apply>"
                  "      <ci> compartmentOne </ci>"
                  "    </apply>"
                  "    <ci> t </ci>"
                  "  </apply>"
                  "</math>";

  astMath = readMathMLFromString(mathXMLString.c_str());
  kl->setMath(astMath);
  delete astMath;


  // Returns the created SBMLDocument object.
  // The returned object must be explicitly deleted by the caller,
  // otherwise memory leak will happen.

  return sbmlDoc;
}
Exemple #7
0
/** @cond doxygenLibsbmlInternal */
int 
Replacing::updateIDs(SBase* oldnames, SBase* newnames)
{
  int ret = LIBSBML_OPERATION_SUCCESS;
  SBMLDocument* doc = getSBMLDocument();
  if (oldnames->isSetId() && !newnames->isSetId()) {
    if (doc) {
      string error = "Unable to transform IDs in Replacing::updateIDs during replacement:  the '" + oldnames->getId() + "' element's replacement does not have an ID set.";
      doc->getErrorLog()->logPackageError("comp", CompMustReplaceIDs, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    }
    return LIBSBML_INVALID_OBJECT;
  }
  if (oldnames->isSetMetaId() && !newnames->isSetMetaId()) {
    if (doc) {
      string error = "Unable to transform IDs in Replacing::updateIDs during replacement:  the replacement of the element with metaid '" + oldnames->getMetaId() + "' does not have a metaid.";
      doc->getErrorLog()->logPackageError("comp", CompMustReplaceMetaIDs, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    }
    return LIBSBML_INVALID_OBJECT;
  }
  //LS DEBUG Somehow we need to check identifiers from other packages here (like spatial id's).  How, exactly, is anyone's guess.
  Model* replacedmod = const_cast<Model*>(CompBase::getParentModel(oldnames));
  KineticLaw* replacedkl;
  ASTNode newkl;
  if (replacedmod==NULL) {
    if (doc) {
      string error = "Unable to transform IDs in Replacing::updateIDs during replacement:  the replacement of '" + oldnames->getId() + "' does not have a valid model.";
      doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    }
    return LIBSBML_INVALID_OBJECT;
  }
  List* allElements = replacedmod->getAllElements();
  string oldid = oldnames->getId();
  string newid = newnames->getId();
  if (!oldid.empty()) {
    switch(oldnames->getTypeCode()) {
    case SBML_UNIT_DEFINITION:
      replacedmod->renameUnitSIdRefs(oldid, newid);
      for (unsigned int e=0; e<allElements->getSize(); e++) {
        SBase* element = static_cast<SBase*>(allElements->get(e));
        element->renameUnitSIdRefs(oldid, newid);
      }
      break;
    case SBML_LOCAL_PARAMETER:
      replacedkl = static_cast<KineticLaw*>(oldnames->getAncestorOfType(SBML_KINETIC_LAW));
      if (replacedkl->isSetMath()) {
        newkl = *replacedkl->getMath();
        newkl.renameSIdRefs(oldid, newid);
        replacedkl->setMath(&newkl);
      }
      break;
    case SBML_COMP_PORT:
      break;
      //LS DEBUG And here is where we would need some sort of way to check if the id wasn't an SId for some objects.
    default:
      replacedmod->renameSIdRefs(oldnames->getId(), newnames->getId());
      for (unsigned int e=0; e<allElements->getSize(); e++) {
        SBase* element = static_cast<SBase*>(allElements->get(e));
        element->renameSIdRefs(oldid, newid);
      }
    }
  }
  string oldmetaid = oldnames->getMetaId();
  string newmetaid = newnames->getMetaId();
  if (oldnames->isSetMetaId()) {
    replacedmod->renameMetaIdRefs(oldmetaid, newmetaid);
    for (unsigned int e=0; e<allElements->getSize(); e++) {
      SBase* element = static_cast<SBase*>(allElements->get(e));
      element->renameMetaIdRefs(oldmetaid, newmetaid);
    }
  }
  //LS DEBUG And here is where we would need some sort of way to check for ids that were not 'id' or 'metaid'.
  delete allElements;
  return ret;
}
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;
}
void Module::CreateSBMLModel()
{
  Model* sbmlmod = m_sbml.createModel();
  sbmlmod->setId(m_modulename);
  sbmlmod->setName(m_modulename);
  sbmlmod->setNotes("<body xmlns=\"http://www.w3.org/1999/xhtml\"><p> Originally created by libAntimony " VERSION_STRING " (using libSBML " LIBSBML_DOTTED_VERSION ") </p></body>");
  char cc = g_registry.GetCC();
  //User-defined functions
  for (size_t uf=0; uf<g_registry.GetNumUserFunctions(); uf++) {
    const UserFunction* userfunction = g_registry.GetNthUserFunction(uf);
    assert(userfunction != NULL);
    FunctionDefinition* fd = sbmlmod->createFunctionDefinition();
    fd->setId(userfunction->GetModuleName());
    ASTNode* math = parseStringToASTNode(userfunction->ToSBMLString());
    fd->setMath(math);
    delete math;
  }
  //Compartments
  Compartment* defaultCompartment = sbmlmod->createCompartment();
  defaultCompartment->setId(DEFAULTCOMP);
  defaultCompartment->setConstant(true);
  defaultCompartment->setSize(1);
  defaultCompartment->setSBOTerm(410); //The 'implicit compartment'
  size_t numcomps = GetNumVariablesOfType(allCompartments);
  for (size_t comp=0; comp<numcomps; comp++) {
    const Variable* compartment = GetNthVariableOfType(allCompartments, comp);
    Compartment* sbmlcomp = sbmlmod->createCompartment();
    sbmlcomp->setId(compartment->GetNameDelimitedBy(cc));
    if (compartment->GetDisplayName() != "") {
      sbmlcomp->setName(compartment->GetDisplayName());
    }
    sbmlcomp->setConstant(compartment->GetIsConst());
    formula_type ftype = compartment->GetFormulaType();
    assert (ftype == formulaINITIAL || ftype==formulaASSIGNMENT || ftype==formulaRATE);
    if (ftype != formulaINITIAL) {
      sbmlcomp->setConstant(false);
    }
    const Formula* formula = compartment->GetFormula();
    if (formula->IsDouble()) {
      sbmlcomp->setSize(atof(formula->ToSBMLString().c_str()));
    }
    SetAssignmentFor(sbmlmod, compartment);
  }

  //Species
  size_t numspecies = GetNumVariablesOfType(allSpecies);
  for (size_t spec=0; spec < numspecies; spec++) {
    const Variable* species = GetNthVariableOfType(allSpecies, spec);
    Species* sbmlspecies = sbmlmod->createSpecies();
    sbmlspecies->setId(species->GetNameDelimitedBy(cc));
    if (species->GetDisplayName() != "") {
      sbmlspecies->setName(species->GetDisplayName());
    }
    sbmlspecies->setConstant(false); //There's no need to try to distinguish between const and var for species.
    if (species->GetIsConst()) {
      sbmlspecies->setBoundaryCondition(true);
    }
    else {
      sbmlspecies->setBoundaryCondition(false);
    }
    const Variable* compartment = species->GetCompartment();
    if (compartment == NULL) {
      sbmlspecies->setCompartment(defaultCompartment->getId());
    }
    else {
      sbmlspecies->setCompartment(compartment->GetNameDelimitedBy(cc));
    }
    const Formula* formula = species->GetFormula();
    if (formula->IsDouble()) {
      sbmlspecies->setInitialConcentration(atof(formula->ToSBMLString().c_str()));
    }
    else if (formula->IsAmountIn(species->GetCompartment())) {
      sbmlspecies->setInitialAmount(formula->ToAmount());
    }
    SetAssignmentFor(sbmlmod, species);
  }

  //Formulas
  size_t numforms = GetNumVariablesOfType(allFormulas);
  for (size_t form=0; form < numforms; form++) {
    const Variable* formvar = GetNthVariableOfType(allFormulas, form);
    const Formula*  formula = formvar->GetFormula();
    Parameter* param = sbmlmod->createParameter();
    param->setId(formvar->GetNameDelimitedBy(cc));
    if (formvar->GetDisplayName() != "") {
      param->setName(formvar->GetDisplayName());
    }
    param->setConstant(formvar->GetIsConst());
    if (formula->IsDouble()) {
      param->setValue(atof(formula->ToSBMLString().c_str()));
    }
    SetAssignmentFor(sbmlmod, formvar);
    formula_type ftype = formvar->GetFormulaType();
    assert (ftype == formulaINITIAL || ftype==formulaASSIGNMENT || ftype==formulaRATE);
    if (ftype != formulaINITIAL) {
      param->setConstant(false);
    }
  }

  //Reactions
  size_t numrxns = GetNumVariablesOfType(allReactions);
  for (size_t rxn=0; rxn < numrxns; rxn++) {
    const Variable* rxnvar = GetNthVariableOfType(allReactions, rxn);
    const AntimonyReaction* reaction = rxnvar->GetReaction();
    if (reaction->IsEmpty()) {
      continue; //Reactions that involve no species are illegal in SBML.
    }
    Reaction* sbmlrxn = sbmlmod->createReaction();
    sbmlrxn->setId(rxnvar->GetNameDelimitedBy(cc));
    if (rxnvar->GetDisplayName() != "") {
      sbmlrxn->setName(rxnvar->GetDisplayName());
    }
    if (reaction->GetType() == rdBecomes) {
      sbmlrxn->setReversible(true);
    }
    else {
      assert(reaction->GetType() == rdBecomesIrreversibly);
      sbmlrxn->setReversible(false);
    }
    const Formula* formula = reaction->GetFormula();
    string formstring = formula->ToSBMLString(rxnvar->GetStrandVars());
    if (!formula->IsEmpty()) {
      KineticLaw* kl = sbmlmod->createKineticLaw();
      ASTNode* math = parseStringToASTNode(formstring);
      kl->setMath(math);
      delete math;
    }
    const ReactantList* left = reaction->GetLeft();
    for (size_t lnum=0; lnum<left->Size(); lnum++) {
      const Variable* nthleft = left->GetNthReactant(lnum);
      double nthstoich = left->GetStoichiometryFor(lnum);
      SpeciesReference* sr = sbmlmod->createReactant();
      sr->setSpecies(nthleft->GetNameDelimitedBy(cc));
      sr->setStoichiometry(nthstoich);
    }
    const ReactantList* right = reaction->GetRight();
    for (size_t rnum=0; rnum<right->Size(); rnum++) {
      const Variable* nthright = right->GetNthReactant(rnum);
      double nthstoich = right->GetStoichiometryFor(rnum);
      SpeciesReference* sr = sbmlmod->createProduct();
      sr->setSpecies(nthright->GetNameDelimitedBy(cc));
      sr->setStoichiometry(nthstoich);
    }
    //Find 'modifiers' and add them.
    vector<const Variable*> subvars = formula->GetVariablesFrom(formstring, m_modulename);
    for (size_t v=0; v<subvars.size(); v++) {
      if (subvars[v] != NULL && subvars[v]->GetType() == varSpeciesUndef) {
        if (left->GetStoichiometryFor(subvars[v]) == 0 &&
            right->GetStoichiometryFor(subvars[v]) == 0) {
          ModifierSpeciesReference* msr = sbmlmod->createModifier();
          msr->setSpecies(subvars[v]->GetNameDelimitedBy(cc));
        }
      }
    }
  }

  //Events
  size_t numevents = GetNumVariablesOfType(allEvents);
  for (size_t ev=0; ev < numevents; ev++) {
    const Variable* eventvar = GetNthVariableOfType(allEvents, ev);
    const AntimonyEvent* event = eventvar->GetEvent();
    Event* sbmlevent = sbmlmod->createEvent();
    sbmlevent->setId(eventvar->GetNameDelimitedBy(cc));
    if (eventvar->GetDisplayName() != "") {
      sbmlevent->setName(eventvar->GetDisplayName());
    }
    Trigger* trig = sbmlevent->createTrigger();
    ASTNode* ASTtrig = parseStringToASTNode(event->GetTrigger()->ToSBMLString());
    trig->setMath(ASTtrig);
    delete ASTtrig;
    const Formula* delay = event->GetDelay();
    if (!delay->IsEmpty()) {
      ASTtrig = parseStringToASTNode(delay->ToSBMLString());
      Delay* sbmldelay = sbmlevent->createDelay();
      sbmldelay->setMath(ASTtrig);
      delete ASTtrig;
    }
      
    long numasnts = static_cast<long>(event->GetNumAssignments());
    for (long asnt=numasnts-1; asnt>=0; asnt--) {
      //events are stored in reverse order.  Don't ask...
      EventAssignment* sbmlasnt = sbmlmod->createEventAssignment();
      sbmlasnt->setVariable(event->GetNthAssignmentVariableName(asnt, cc));
      ASTNode* ASTasnt = parseStringToASTNode(event->GetNthAssignmentFormulaString(asnt, '_', true));
      sbmlasnt->setMath(ASTasnt);
      delete ASTasnt;
    }
  }

  //Interactions
  size_t numinteractions = GetNumVariablesOfType(allInteractions);
  for (size_t irxn=0; irxn<numinteractions; irxn++) {
    const Variable* arxnvar = GetNthVariableOfType(allInteractions, irxn);
    const AntimonyReaction* arxn = arxnvar->GetReaction();
    Reaction* rxn = sbmlmod->getReaction(arxn->GetRight()->GetNthReactant(0)->GetNameDelimitedBy(cc));
    if (rxn != NULL) {
      for (size_t interactor=0; interactor<arxn->GetLeft()->Size(); interactor++) {
        ModifierSpeciesReference* msr = rxn->createModifier();
        msr->setSpecies(arxn->GetLeft()->GetNthReactant(interactor)->GetNameDelimitedBy(cc));
        msr->setName(arxnvar->GetNameDelimitedBy(cc));
      }
    }
  }

  //Unknown variables (turn into parameters)
  size_t numunknown = GetNumVariablesOfType(allUnknown);
  for (size_t form=0; form < numunknown; form++) {
    const Variable* formvar = GetNthVariableOfType(allUnknown, form);
    Parameter* param = sbmlmod->createParameter();
    param->setId(formvar->GetNameDelimitedBy(cc));
    if (formvar->GetDisplayName() != "") {
      param->setName(formvar->GetDisplayName());
    }
    switch(formvar->GetConstType()) {
    case constVAR:
      param->setConstant(true);
      break;
    case constCONST:
      param->setConstant(false);
      break;
    case constDEFAULT:
      break;
    }
  }
}