END_TEST

START_TEST(test_FbcExtension_create_and_write_new_geneassociation
)
{
  FbcPkgNamespaces *sbmlns = new FbcPkgNamespaces(3, 1, 2);

  // create the document

  SBMLDocument document(sbmlns);
  document.setConsistencyChecks(LIBSBML_CAT_UNITS_CONSISTENCY, false);
  document.setConsistencyChecks(LIBSBML_CAT_MODELING_PRACTICE, false);

  // create the Model

  Model* model = document.createModel();

  // create the Compartment

  Compartment* compartment = model->createCompartment();
  compartment->setId("compartment");
  compartment->setConstant(true);
  compartment->setSize(1);

  // create the Species

  Species* species = model->createSpecies();
  species->setId("Node1");
  species->setCompartment("compartment");
  species->setBoundaryCondition(false);

  species = model->createSpecies();
  species->setId("Node2");
  species->setCompartment("compartment");
  species->setBoundaryCondition(false);

  Reaction* reaction = model->createReaction();
  reaction->setId("J0");
  reaction->setReversible(false);
  SpeciesReference* reactant = reaction->createReactant();
  reactant->setSpecies("Node0");
  reactant->setStoichiometry(1);
  SpeciesReference* product = reaction->createProduct();
  product->setSpecies("Node1");
  product->setStoichiometry(1);

  // use fbc

  FbcModelPlugin* mplugin = static_cast<FbcModelPlugin*>(model->getPlugin("fbc"));

  fail_unless(mplugin != NULL);

  FluxBound* bound = mplugin->createFluxBound();

  bound->setId("bound1");
  bound->setReaction("J0");
  bound->setOperation("equal");
  bound->setValue(10);

  Objective* objective = mplugin->createObjective();
  objective->setId("obj1");
  objective->setType("maximize");

  FluxObjective* fluxObjective = objective->createFluxObjective();
  fluxObjective->setReaction("J0");
  fluxObjective->setCoefficient(1);

  FbcReactionPlugin* rplug = dynamic_cast<FbcReactionPlugin*>(reaction->getPlugin("fbc"));
  fail_unless(rplug != NULL);

  GeneProductAssociation * ga = rplug->createGeneProductAssociation();
  ga->setId("ga1");
  ga->setAssociation("MG_077 AND MG_321 AND MG_080 AND MG_078 AND MG_079");
  fail_unless(ga->getAssociation() != NULL);

  fail_unless(mplugin->getNumGeneProducts() == 5);

  ga->setAssociation("MG_077 AND MG_321 AND MG_080 AND MG_078 AND MG_079");
  fail_unless(ga->getAssociation() != NULL);

  fail_unless(mplugin->getNumGeneProducts() == 5);


  delete sbmlns;

}
END_TEST

  START_TEST(test_FbcAssociation_parseFbcInfixAssociation_strange_labels)
{	
  const char* model1 =
    "<?xml version='1.0' encoding='UTF-8'?>"
    "<sbml xmlns:html='http://www.w3.org/1999/xhtml' xmlns='http://www.sbml.org/sbml/level3/version1/core' xmlns:fbc='http://www.sbml.org/sbml/level3/version1/fbc/version2' level='3' version='1' fbc:required='false'>"
    "  <model id='M' name='E' timeUnits='dimensionless' fbc:strict='false'>"
    "    <listOfCompartments>"
    "      <compartment id=\"comp1\" spatialDimensions=\"3\" size=\"1\" constant=\"true\"/>"
    "    </listOfCompartments>"
    "    <listOfSpecies>"
    "       <species id=\"S\" compartment=\"comp1\" initialAmount=\"1\" hasOnlySubstanceUnits=\"false\" boundaryCondition=\"false\" constant=\"false\" fbc:charge=\"2\" fbc:chemicalFormula=\"S20\"/>"
    "    </listOfSpecies>"
    "    <listOfReactions>"
    "      <reaction id=\"R1\" reversible=\"false\" fast=\"false\" fbc:lowerFluxBound=\"low\" fbc:upperFluxBound=\"up\">"
    "    <listOfReactants>"
    "    <speciesReference species=\"S1\" stoichiometry=\"1\" constant=\"true\"/>"
    "    </listOfReactants>"
    "    </reaction>"
    "    </listOfReactions>"
    "  </model>"
    "</sbml>"
    ;
    const char* expected =
    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    "<sbml xmlns:html=\"http://www.w3.org/1999/xhtml\" xmlns=\"http://www.sbml.org/sbml/level3/version1/core\" xmlns:fbc=\"http://www.sbml.org/sbml/level3/version1/fbc/version2\" level=\"3\" version=\"1\" fbc:required=\"false\">\n"
    "  <model id=\"M\" name=\"E\" timeUnits=\"dimensionless\" fbc:strict=\"false\">\n"
    "    <listOfCompartments>\n"
    "      <compartment id=\"comp1\" spatialDimensions=\"3\" size=\"1\" constant=\"true\"/>\n"
    "    </listOfCompartments>\n"
    "    <listOfSpecies>\n"
    "      <species id=\"S\" compartment=\"comp1\" initialAmount=\"1\" hasOnlySubstanceUnits=\"false\" boundaryCondition=\"false\" constant=\"false\" fbc:charge=\"2\" fbc:chemicalFormula=\"S20\"/>\n"
    "    </listOfSpecies>\n"
    "    <listOfReactions>\n"
    "      <reaction id=\"R1\" reversible=\"false\" fast=\"false\" fbc:lowerFluxBound=\"low\" fbc:upperFluxBound=\"up\">\n"
    "        <listOfReactants>\n"
    "          <speciesReference species=\"S1\" stoichiometry=\"1\" constant=\"true\"/>\n"
    "        </listOfReactants>\n"
    "        <fbc:geneProductAssociation fbc:id=\"gg1\">\n"
    "          <fbc:and>\n"
    "            <fbc:geneProductRef fbc:geneProduct=\"gp_g__DOT__p\"/>\n"
    "            <fbc:geneProductRef fbc:geneProduct=\"gp___ONE__sd\"/>\n"
    "          </fbc:and>\n"
    "        </fbc:geneProductAssociation>\n"
    "      </reaction>\n"
    "    </listOfReactions>\n"
    "    <fbc:listOfGeneProducts>\n"
    "      <fbc:geneProduct fbc:id=\"gp_g__DOT__p\" fbc:label=\"g.p\"/>\n"
    "      <fbc:geneProduct fbc:id=\"gp___ONE__sd\" fbc:label=\"1sd\"/>\n"
    "    </fbc:listOfGeneProducts>\n"
    "  </model>\n"
    "</sbml>\n"
    ;

  std::string infix = "(g.p and 1sd)";

  SBMLDocument* doc = readSBMLFromString(model1);
  fail_unless(doc->getModel() != NULL);
  FbcModelPlugin* fbc = dynamic_cast<FbcModelPlugin*>(doc->getModel()->getPlugin("fbc"));
  fail_unless(fbc != NULL);
  fail_unless(fbc->getNumGeneProducts() == 0);

  Reaction * r = doc->getModel()->getReaction(0);
  fail_unless(r != NULL);
  FbcReactionPlugin * rplug =  dynamic_cast<FbcReactionPlugin*>(r->getPlugin("fbc"));
  fail_unless (rplug != NULL);
  fail_unless(rplug->isSetGeneProductAssociation() == false);

  GeneProductAssociation* gpa = rplug->createGeneProductAssociation();
  gpa->setId("gg1");
  FbcAssociation * fa = FbcAssociation::parseFbcInfixAssociation(infix, fbc);
  fail_unless(fa->isFbcAnd() == true);

  gpa->setAssociation(fa);
  fail_unless(rplug->isSetGeneProductAssociation() == true);
  fail_unless(fbc->getNumGeneProducts() == 2);

  GeneProduct* gp = fbc->getGeneProduct(0);
  fail_unless (gp->isSetId() == true);
  fail_unless (gp->isSetLabel() == true);
  
  FbcAssociation * fa_retrieved = gpa->getAssociation();
  fail_unless(fa_retrieved->isFbcAnd() == true);

  std::string out = fa_retrieved->toInfix();
  // if it goes back to infix surely it should be the same infix that it started as
  fail_unless(fa_retrieved->toInfix() == infix);
  
  //GeneProductRef * gpref = dynamic_cast<GeneProductRef *>(gpa->getAssociation());
  //fail_unless(gpref->isSetGeneProduct() == true);

  //fail_unless(gpref->getGeneProduct() == gp->getId());

  char * char_doc = writeSBMLToString(doc);
  fail_unless(equals(expected, char_doc));

  safe_free((void*)(char_doc));

  delete fa;
  delete doc;
}