LIBSBML_CPP_NAMESPACE_USE

int main(int argc,char** argv)
{

  if (argc != 2)
  {
    std::cout << "Usage: example1\n";
    return 1;
  }

  //
  // Creates an SBMLNamespaces object with the given SBML level, version
  // package name, package version.
  //
  // (NOTE) By defualt, the name of package (i.e. "qual") will be used
  // if the arugment for the prefix is missing or empty. Thus the argument
  // for the prefix can be added as follows:
  //
  //    SBMLNamespaces sbmlns(3,1,"qual",1,"QUAL");
  //

  SBMLNamespaces sbmlns(3,1,"qual",1);

  //
  // (NOTES) The above code creating an SBMLNamespaces object can be replaced 
  //         with one of the following other styles.
  //
  // (1) Creates an SBMLNamespace object with a SBML core namespace and then
  //     adds a qual package namespace to the object.
  //
  //         SBMLNamespaces sbmlns(3,1);
  //         sbmlns.addPkgNamespace("qual",1);
  //
  //          OR
  //
  //         SBMLNamespaces sbmlns(3,1);
  //         sbmlns.addNamespace(QualExtension::XmlnsL3V1V1,"qual");
  //
  // (2) Creates a QualPkgNamespaces object (SBMLNamespace derived class for
  //     qual package. The class is basically used for createing an SBase
  //     derived objects defined in the qual package) with the given SBML
  //     level, version, and package version
  //
  //        QualPkgNamespaces sbmlns(3,1,1);
  //     


  // create the document

  SBMLDocument *document = new SBMLDocument(&sbmlns);

  // mark qual as required

  document->setPackageRequired("qual", true);


  // create the Model

  Model* model=document->createModel();

  // create the Compartment

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

  //
  // Get a QualModelPlugin object plugged in the model object.
  //
  // The type of the returned value of SBase::getPlugin() function is
  // SBasePlugin*, and thus the value needs to be casted for the
  // corresponding derived class.
  //
  QualModelPlugin* mplugin
    = static_cast<QualModelPlugin*>(model->getPlugin("qual"));

  // create the QualitativeSpecies
  QualitativeSpecies* qs = mplugin->createQualitativeSpecies();
  qs->setId("s1");
  qs->setCompartment("c");
  qs->setConstant(false);
  qs->setInitialLevel(1);
  qs->setMaxLevel(4);
  qs->setName("sss");

  // create the Transition
  Transition* t = mplugin->createTransition();
  t->setId("d");
  t->setSBOTerm(1);

  Input* i = t->createInput();
  i->setId("RD");
  i->setQualitativeSpecies("s1");
  i->setTransitionEffect(INPUT_TRANSITION_EFFECT_NONE);
  i->setSign(INPUT_SIGN_NEGATIVE);
  i->setThresholdLevel(2);
  i->setName("aa");

  Output* o = t->createOutput();
  o->setId("wd");
  o->setQualitativeSpecies("s1");
  o->setTransitionEffect(OUTPUT_TRANSITION_EFFECT_PRODUCTION);
  o->setOutputLevel(2);
  o->setName("aa");

  DefaultTerm* dt = t->createDefaultTerm();
  dt->setResultLevel(2) ;

  FunctionTerm* ft = t->createFunctionTerm();
  ASTNode* math = SBML_parseL3Formula("geq(s1, 2)");
  ft->setResultLevel(1);
  ft->setMath(math);
  
  writeSBML(document,"qual_example1.xml");
  delete document;

  return 0;
}
END_TEST


START_TEST (test_QualExtension_read_enable_via_sbmldocument_and_write_L3V1V1)
{
  const char* s1 =
    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    "<sbml xmlns=\"http://www.sbml.org/sbml/level3/version1/core\" level=\"3\" version=\"1\">\n"
    "  <model>\n"
    "    <listOfCompartments>\n"
    "      <compartment id=\"c\" constant=\"true\"/>\n"
    "    </listOfCompartments>\n"
    "  </model>\n"
    "</sbml>\n"
    ;

  const char* s1a =
    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    "<sbml xmlns=\"http://www.sbml.org/sbml/level3/version1/core\" xmlns:qual=\"http://www.sbml.org/sbml/level3/version1/qual/version1\" level=\"3\" version=\"1\" qual:required=\"true\">\n"
    "  <model>\n"
    "    <listOfCompartments>\n"
    "      <compartment id=\"c\" constant=\"true\"/>\n"
    "    </listOfCompartments>\n"
    "    <qual:listOfQualitativeSpecies>\n"
    "      <qual:qualitativeSpecies qual:id=\"s1\" qual:compartment=\"c\" qual:constant=\"false\" qual:name=\"sss\" qual:initialLevel=\"1\" qual:maxLevel=\"4\"/>\n"
    "    </qual:listOfQualitativeSpecies>\n"
    "  </model>\n"
    "</sbml>\n"
    ;

  SBMLDocument *document = readSBMLFromString(s1);

  fail_unless(document->getNumPlugins()             == 0);

  //
  // enable the qual package by invoking enablePackage function with SBMLDocument object
  //
  fail_unless(document->enablePackage(QUAL_XMLNS_L3V1V1, "qual", true) == LIBSBML_OPERATION_SUCCESS);

  // mark qual as required

  document->setPackageRequired("qual", true);

  fail_unless(document->getNumPlugins()             == 1);

  Model *model = document->getModel();

  fail_unless(model != NULL);
  fail_unless(model->getNumPlugins() == 1);

  //// create the QualitativeSpecies

  QualModelPlugin* mplugin = static_cast<QualModelPlugin*>(model->getPlugin("qual"));

  fail_unless(mplugin != NULL);

  QualitativeSpecies* qs = mplugin->createQualitativeSpecies();
  fail_unless(qs->setId("s1")               == LIBSBML_OPERATION_SUCCESS);
  fail_unless(qs->setCompartment("c")       == LIBSBML_OPERATION_SUCCESS);
  fail_unless(qs->setConstant(false)        == LIBSBML_OPERATION_SUCCESS);
  fail_unless(qs->setInitialLevel(1)        == LIBSBML_OPERATION_SUCCESS);
  fail_unless(qs->setMaxLevel(4)            == LIBSBML_OPERATION_SUCCESS);
  fail_unless(qs->setName("sss")            == LIBSBML_OPERATION_SUCCESS);

  char *s2 = writeSBMLToString(document);

  fail_unless(strcmp(s1a,s2) == 0); 
  
  free(s2);
  delete document;  
}
END_TEST


START_TEST (test_QualExtension_read_L3V1V1_defaultNS)
{
  string filename = string(TestDataDirectory) + "qual-example1-defaultNS.xml";
  SBMLDocument *document = readSBMLFromFile(filename.c_str());
  
  fail_unless(document->getPackageName() == "core");

  Model *model = document->getModel();

  fail_unless(model != NULL);
  fail_unless(model->getPackageName() == "core");

  // get the Qualitative species

  QualModelPlugin* mplugin = static_cast<QualModelPlugin*>(model->getPlugin("qual"));
  fail_unless(mplugin != NULL);

  fail_unless(mplugin->getNumQualitativeSpecies() == 1);
  fail_unless(mplugin->getListOfQualitativeSpecies()->getPackageName() == "qual");

  fail_unless(mplugin->getNumTransitions() == 1);
  fail_unless(mplugin->getListOfTransitions()->getPackageName() == "qual");

  QualitativeSpecies* qs = mplugin->getQualitativeSpecies(0);
  fail_unless(qs->getPackageName() == "qual");
  fail_unless(qs->getId() == "s1");
  fail_unless(qs->getName() == "sss");
  fail_unless(qs->getMetaId() == "_ddd");
  fail_unless(qs->getCompartment() == "c");
  fail_unless(qs->getConstant() == false);
  fail_unless(qs->getInitialLevel() == 1);
  fail_unless(qs->getMaxLevel() == 4);

  Transition* t = mplugin->getTransition(0);

  
  fail_unless(t->getPackageName() == "qual");
  fail_unless(t->getId() == "d");
  fail_unless(t->getNumInputs() == 1);
  fail_unless(t->getNumOutputs() == 1);
  fail_unless(t->getNumFunctionTerms() == 1);
  fail_unless(t->isSetDefaultTerm() == true);

  Input *i = t->getInput(0);
  
  fail_unless(i->getPackageName() == "qual");
  fail_unless(i->getId() == "RD");
  fail_unless(i->getName() == "aa" );
  fail_unless(i->getQualitativeSpecies() == "s1");
  fail_unless(i->getTransitionEffect() == INPUT_TRANSITION_EFFECT_NONE );
  fail_unless(i->getSign() == INPUT_SIGN_NEGATIVE);
  fail_unless(i->getThresholdLevel() == 2);

  Output *o = t->getOutput(0);
  
  fail_unless(o->getPackageName() == "qual");
  fail_unless(o->getId() == "wd");
  fail_unless(o->getName() == "asa" );
  fail_unless(o->getQualitativeSpecies() == "s1");
  fail_unless(o->getTransitionEffect() == OUTPUT_TRANSITION_EFFECT_PRODUCTION );
  fail_unless(o->getOutputLevel() == 2);

  FunctionTerm* ft1 = t->getFunctionTerm(0);

  fail_unless(ft1->getPackageName() == "qual");
  fail_unless(ft1->getResultLevel() == 1);
  fail_unless(ft1->getMath() != NULL);

  DefaultTerm* dt = t->getDefaultTerm();

  fail_unless(dt->getPackageName() == "qual");
  fail_unless(dt->getResultLevel() == 2);


  delete document;  
}
END_TEST


START_TEST (test_QualExtension_create_add_and_write_L3V1V1)
{
  const char* s1 =
    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    "<sbml xmlns=\"http://www.sbml.org/sbml/level3/version1/core\" xmlns:qual=\"http://www.sbml.org/sbml/level3/version1/qual/version1\" level=\"3\" version=\"1\" qual:required=\"true\">\n"
    "  <model>\n"
    "    <listOfCompartments>\n"
    "      <compartment id=\"c\" constant=\"true\"/>\n"
    "    </listOfCompartments>\n"
    "    <qual:listOfQualitativeSpecies>\n"
    "      <qual:qualitativeSpecies metaid=\"ddd\" qual:id=\"s1\" qual:compartment=\"c\" qual:constant=\"false\" qual:name=\"sss\" qual:initialLevel=\"1\" qual:maxLevel=\"4\"/>\n"
    "    </qual:listOfQualitativeSpecies>\n"
    "    <qual:listOfTransitions>\n"
    "      <qual:transition sboTerm=\"SBO:0000001\" qual:id=\"d\">\n"
    "        <qual:listOfInputs>\n"
    "          <qual:input qual:id=\"RD\" qual:qualitativeSpecies=\"s1\" qual:transitionEffect=\"none\" qual:name=\"aa\" qual:sign=\"negative\" qual:thresholdLevel=\"2\"/>\n"
    "        </qual:listOfInputs>\n"
    "        <qual:listOfOutputs>\n"
    "          <qual:output qual:id=\"wd\" qual:qualitativeSpecies=\"s1\" qual:transitionEffect=\"production\" qual:name=\"aa\" qual:outputLevel=\"2\"/>\n"
    "        </qual:listOfOutputs>\n"
    "        <qual:listOfFunctionTerms>\n"
		"          <qual:defaultTerm qual:resultLevel=\"1\"/>\n"
		"          <qual:functionTerm qual:resultLevel=\"2\">\n"
    "            <math xmlns=\"http://www.w3.org/1998/Math/MathML\">\n"
		"              <apply>\n"
		"                <geq/>\n"
		"                <ci> s1 </ci>\n"
		"                <cn type=\"integer\"> 2 </cn>\n"
		"              </apply>\n"
		"            </math>\n"
		"          </qual:functionTerm>\n"
		"        </qual:listOfFunctionTerms>\n"
    "      </qual:transition>\n"
    "    </qual:listOfTransitions>\n"
    "  </model>\n"
    "</sbml>\n"
    ;

  QualPkgNamespaces *sbmlns = new QualPkgNamespaces(3,1,1);

  // create the document

  SBMLDocument *document = new SBMLDocument(sbmlns);

  //// mark qual as required

  document->setPackageRequired("qual", true);

  // create the Model

  Model* model= new Model(sbmlns);

  // create the Compartment

  Compartment* compartment = new Compartment(sbmlns);
  compartment->setId("c");
  compartment->setConstant(true);

  fail_unless(model->addCompartment(compartment) == LIBSBML_OPERATION_SUCCESS);

  //// create the QualitativeSpecies

  QualModelPlugin* mplugin = static_cast<QualModelPlugin*>(model->getPlugin("qual"));

  fail_unless(mplugin != NULL);

  QualitativeSpecies* qs = new QualitativeSpecies(sbmlns); 
  fail_unless(qs->setId("s1")               == LIBSBML_OPERATION_SUCCESS);
  fail_unless(qs->setCompartment("c")       == LIBSBML_OPERATION_SUCCESS);
  fail_unless(qs->setConstant(false)        == LIBSBML_OPERATION_SUCCESS);
  fail_unless(qs->setInitialLevel(1)        == LIBSBML_OPERATION_SUCCESS);
  fail_unless(qs->setMaxLevel(4)            == LIBSBML_OPERATION_SUCCESS);
  fail_unless(qs->setName("sss")            == LIBSBML_OPERATION_SUCCESS);
  fail_unless(qs->setMetaId("ddd")          == LIBSBML_OPERATION_SUCCESS);

  fail_unless(mplugin->addQualitativeSpecies(qs) == LIBSBML_OPERATION_SUCCESS);

  Transition* t = new Transition(sbmlns);
  fail_unless(t->setId("d")               == LIBSBML_OPERATION_SUCCESS);
  fail_unless(t->setSBOTerm(1)            == LIBSBML_OPERATION_SUCCESS);

  Input* i = new Input(sbmlns);
  fail_unless(i->setId("RD")                 == LIBSBML_OPERATION_SUCCESS);
  fail_unless(i->setQualitativeSpecies("s1") == LIBSBML_OPERATION_SUCCESS);
  fail_unless(i->setTransitionEffect
  (InputTransitionEffect_fromString("none")) == LIBSBML_OPERATION_SUCCESS);
  fail_unless(i->setSign(InputSign_fromString("negative"))
                                             == LIBSBML_OPERATION_SUCCESS);
  fail_unless(i->setThresholdLevel(2)        == LIBSBML_OPERATION_SUCCESS);
  fail_unless(i->setName("aa")               == LIBSBML_OPERATION_SUCCESS);

  fail_unless(t->addInput(i) == LIBSBML_OPERATION_SUCCESS);

  Output* o = new Output(sbmlns);
  fail_unless(o->setId("wd")                       == LIBSBML_OPERATION_SUCCESS);
  fail_unless(o->setQualitativeSpecies("s1")       == LIBSBML_OPERATION_SUCCESS);
  fail_unless(o->setTransitionEffect
  (OutputTransitionEffect_fromString("production")) == LIBSBML_OPERATION_SUCCESS);
  fail_unless(o->setOutputLevel(2)                 == LIBSBML_OPERATION_SUCCESS);
  fail_unless(o->setName("aa")                     == LIBSBML_OPERATION_SUCCESS);

  fail_unless(t->addOutput(o) == LIBSBML_OPERATION_SUCCESS);

  FunctionTerm* ft = new FunctionTerm(sbmlns);
  ASTNode* math = SBML_parseL3Formula("geq(s1, 2)");
  fail_unless(ft->setResultLevel(2) == LIBSBML_OPERATION_SUCCESS);
  fail_unless(ft->setMath(math)     == LIBSBML_OPERATION_SUCCESS);

  fail_unless(t->addFunctionTerm(ft) == LIBSBML_OPERATION_SUCCESS);

  DefaultTerm* dt = new DefaultTerm(sbmlns);
  fail_unless(dt->setResultLevel(1) == LIBSBML_OPERATION_SUCCESS);


  fail_unless(t->setDefaultTerm(dt) == LIBSBML_OPERATION_SUCCESS);

  fail_unless(mplugin->addTransition(t) == LIBSBML_OPERATION_SUCCESS);

  fail_unless(document->setModel(model) == LIBSBML_OPERATION_SUCCESS);

  char *s2 = writeSBMLToString(document);

  fail_unless(strcmp(s1,s2) == 0); 

  free(s2);

  delete document;  
}