END_TEST
  
START_TEST (test_comp_flatten_exchange5)
{ 
  string filename(TestDataDirectory);
  //string filename("C:\\Development\\libsbml\\src\\sbml\\packages\\comp\\util\\test\\test-data\\");
  
  // load document
  string cfile = filename + "CompTest_A.xml";  
  SBMLDocument* doc = readSBMLFromFile(cfile.c_str());

  Model* model = doc->getModel();
  // fail if there is no model (readSBMLFromFile always returns a valid document)
  fail_unless(model != NULL);

  // SK - since I made the flattenModel package protected
  // this will no longer work
  // ===========
  //CompModelPlugin* cmp = static_cast<CompModelPlugin*>(model->getPlugin("comp"));

  //Model* flatmod = cmp->flattenModel();
  //fail_unless(flatmod != NULL);
  //CompPkgNamespaces csbmlns(3,1,1,"comp");
  //SBMLDocument flatdoc(&csbmlns);
  //flatdoc.setPackageRequired("comp", true);
  //flatdoc.setModel(flatmod);
  //writeSBMLToFile(&flatdoc, "CompTest_flat_ports.xml");

  //string newModel = writeSBMLToString(&flatdoc);
  //===========
  // replace with

  ConversionProperties* props = new ConversionProperties();
  
  props->addOption("flatten comp");
  props->addOption("leavePorts", true);

  SBMLConverter* converter = SBMLConverterRegistry::getInstance().getConverterFor(*props);
  converter->setDocument(doc);
  int result = converter->convert();

  // fail if conversion was not valid
  fail_unless(result == LIBSBML_OPERATION_SUCCESS);

  string newModel = writeSBMLToString(doc);

  string ffile = filename + "CompTest_flat_ports.xml";
  SBMLDocument* fdoc = readSBMLFromFile(ffile.c_str());
  string flatModel = writeSBMLToString(fdoc);
  fail_unless(flatModel == newModel);

  delete doc;
  delete fdoc;
}
END_TEST


START_TEST (test_conversion_ruleconverter_with_alg)
{
  // create test model

  SBMLDocument doc; 

  Model* model = doc.createModel();
  model->setId("m");

  Parameter* parameter1 = model->createParameter();
  parameter1->setId("s");
  parameter1->setConstant(false);
  parameter1->setValue(0);

  Parameter* parameter = model->createParameter();
  parameter->setId("p");
  parameter->setConstant(false);
  parameter->setValue(0);

  Parameter* parameter2 = model->createParameter();
  parameter2->setId("k");
  parameter2->setConstant(false);
  parameter2->setValue(0);

  AlgebraicRule* rule0 = model->createAlgebraicRule();
  rule0->setFormula("k + 2");
  rule0->setMetaId("m0");

  AssignmentRule* rule1 = model->createAssignmentRule();
  rule1->setVariable("s");
  rule1->setFormula("p + 1");
  rule1->setMetaId("m1");

  AssignmentRule* rule2 = model->createAssignmentRule();
  rule2->setVariable("p");
  rule2->setFormula("1");
  rule2->setMetaId("m2");

  ConversionProperties props;
  props.addOption("sortRules", true, "sort rules");

  SBMLConverter* converter = new SBMLRuleConverter();
  converter->setProperties(&props);
  converter->setDocument(&doc);
  fail_unless (converter->convert() == LIBSBML_OPERATION_SUCCESS);

  fail_unless (model->getNumRules() == 3);
  fail_unless (model->getRule(0)->getMetaId() == "m2");
  fail_unless (model->getRule(1)->getMetaId() == "m1");
  fail_unless (model->getRule(2)->getMetaId() == "m0");
}
SBMLDocument* TestFlattenedUnknownAbortNone(string file1, string file2)
{
  string filename(TestDataDirectory);
  //string filename("C:\\Development\\libsbml\\src\\sbml\\packages\\comp\\util\\test\\test-data\\");
  
  ConversionProperties props;
  
  props.addOption("flatten comp");
  props.addOption("basePath", filename);
  props.addOption("performValidation", false);
  props.addOption("abortIfUnflattenable", "none");

  SBMLConverter* converter = SBMLConverterRegistry::getInstance().getConverterFor(props);
  
  // load document
  string cfile = filename + file1;  
  SBMLDocument* doc = readSBMLFromFile(cfile.c_str());

  // fail if there is no model (readSBMLFromFile always returns a valid document)
  fail_unless(doc->getModel() != NULL);

  converter->setDocument(doc);
  int result = converter->convert();

  // fail if conversion was not valid
  fail_unless(result == LIBSBML_OPERATION_SUCCESS);

  //For use in debugging the above statement.
  /*
  SBMLErrorLog* errors = doc->getErrorLog();
  if (errors->getNumFailsWithSeverity(LIBSBML_SEV_ERROR) != 0) {
    fail_unless(false);
    for (unsigned long e=0; e<errors->getNumErrors(); e++) {
      const SBMLError* error = errors->getError(e);
      if (error->getSeverity() == LIBSBML_SEV_ERROR) {
        cout << error->getMessage() << endl;
      }
    }
  }
  */

  string newModel = writeSBMLToStdString(doc);
  //string outfile = filename + "unknown_flat.xml";
  //writeSBMLToFile(doc, outfile.c_str());
  string ffile = filename + file2;
  SBMLDocument* fdoc = readSBMLFromFile(ffile.c_str());
  string flatModel = writeSBMLToStdString(fdoc);
  fail_unless(flatModel == newModel);

  delete fdoc;
  delete converter;

  return doc;
}
END_TEST



START_TEST (test_conversion_ruleconverter_sortIA)
{

  // create test model

  SBMLDocument doc; 

  Model* model = doc.createModel();
  model->setId("m");

  Parameter* parameter1 = model->createParameter();
  parameter1->setId("s");
  parameter1->setConstant(false);
  parameter1->setValue(0);

  Parameter* parameter = model->createParameter();
  parameter->setId("p");
  parameter->setConstant(false);
  parameter->setValue(0);

  InitialAssignment* ia1 = model->createInitialAssignment();
  ia1->setSymbol("s");
  ASTNode * math = SBML_parseFormula("p + 1");
  ia1->setMath(math);
  delete math;
  ia1->setMetaId("m1");

  InitialAssignment* ia2 = model->createInitialAssignment();
  ia2->setSymbol("p");
  math = SBML_parseFormula("1");
  ia2->setMath(math);
  delete math;
  ia2->setMetaId("m2");

  ConversionProperties props;
  props.addOption("sortRules", true, "sort rules");

  SBMLConverter* converter = new SBMLRuleConverter();
  converter->setProperties(&props);
  converter->setDocument(&doc);
  
  fail_unless (converter->convert() == LIBSBML_OPERATION_SUCCESS);
  fail_unless (model->getNumInitialAssignments() == 2);
  fail_unless (model->getInitialAssignment(0)->getMetaId() == "m2");
  fail_unless (model->getInitialAssignment(1)->getMetaId() == "m1");

  delete converter;
}
LIBSBML_CPP_NAMESPACE_USE

  int
  main (int argc, char* argv[])
{
  if (argc != 3)
  {
    cout << endl << "Usage: inferUnits input-filename output-filename"
      << endl << endl;
    return 2;
  }

  SBMLDocument *d = readSBML(argv[1]);
  d->checkConsistency();
  if ( d->getNumErrors(LIBSBML_SEV_ERROR) > 0)
  {
    d->printErrors();
  }
  else
  {
    /* create a new conversion properties structure */
    ConversionProperties* props = new ConversionProperties();
  
    /* add an option that we want to infer units */
    props->addOption("inferUnits");

    SBMLConverter* converter = 
           SBMLConverterRegistry::getInstance().getConverterFor(*props);
  

    converter->setDocument(d);

    /* perform the conversion */
    if (converter->convert() != LIBSBML_OPERATION_SUCCESS)
    {
      cout<< "conversion failed ... " << endl;
      return 3;
    }

    d->getErrorLog()->clearLog();
    d->validateSBML();
    d->printErrors(cout);

    writeSBML(d, argv[2]);
  }

  return 0;
}
END_TEST


START_TEST (test_comp_flatten_unknown_21)
{ 
  string filename(TestDataDirectory);
  //string filename("C:\\Development\\libsbml\\src\\sbml\\packages\\comp\\util\\test\\test-data\\");
  
  ConversionProperties props;
  
  props.addOption("flatten comp");
  props.addOption("basePath", filename);
  props.addOption("performValidation", false);

  SBMLConverter* converter = SBMLConverterRegistry::getInstance().getConverterFor(props);
  
  // load document
  string cfile = filename + "flatten_fail_unknown.xml";  
  SBMLDocument* doc = readSBMLFromFile(cfile.c_str());

  // fail if there is no model (readSBMLFromFile always returns a valid document)
  fail_unless(doc->getModel() != NULL);

  // write the doc before we attempt conversion
  string newModel = writeSBMLToStdString(doc);

  converter->setDocument(doc);
  int result = converter->convert();

  // we should fail because we are testing the restoreNamespaces function
  fail_unless(result == LIBSBML_OPERATION_FAILED);


  string flatModel = writeSBMLToStdString(doc);
  fail_unless(flatModel == newModel);

  delete converter; 

  SBMLErrorLog* errors = doc->getErrorLog();
  fail_unless(errors->getNumErrors() == 2);
  fail_unless(errors->contains(RequiredPackagePresent) == true);
  fail_unless(errors->contains(CompFlatteningNotRecognisedReqd) == true);
  //fail_unless(errors->contains(CompModelFlatteningFailed) == true);
  //fail_unless(errors->contains(CompSubmodelMustReferenceModel) == true);

  delete doc;  
}
void TestPairNoStrip(std::string file1, std::string file2, std::string pkgToStrip,
              unsigned int numErrors = 0)
{
  std::string filename(TestDataDirectory);
  std::string dir("test_external_flat_strip/");

  ConversionProperties props;
  
  props.addOption("flatten comp");
  props.addOption("basePath", filename);
  props.addOption("performValidation", true);
  props.addOption("stripPackages", pkgToStrip);
  props.addOption("abortIfUnflattenable", "none");
  props.addOption("stripUnflattenablePackages", false);

  SBMLConverter* converter = SBMLConverterRegistry::getInstance().
                                                    getConverterFor(props);
  
  // load document
  std::string cfile = filename + dir + file1;  
  SBMLDocument* doc = readSBMLFromFile(cfile.c_str());

  // fail if there is no model (readSBMLFromFile always returns a valid doc)
  fail_unless(doc->getModel() != NULL);

  fail_unless(doc->getErrorLog()->getNumFailsWithSeverity(LIBSBML_SEV_ERROR) 
                                                          == numErrors);

  converter->setDocument(doc);
  int result = converter->convert();

  // fail if conversion was not valid
  fail_unless(result == LIBSBML_OPERATION_SUCCESS);

  std::string newModel = writeSBMLToStdString(doc);
  
  std::string ffile = filename + dir + file2;
  SBMLDocument* fdoc = readSBMLFromFile(ffile.c_str());
  std::string flatModel = writeSBMLToStdString(fdoc);

  fail_unless(flatModel == newModel);

  delete doc;
  delete fdoc;
  delete converter;
}
END_TEST

START_TEST (test_comp_model_flattening_with_ports)
{
  string filename(TestDataDirectory);
  string cfile = filename + "test14_A.xml";  
  SBMLDocument* doc = readSBMLFromFile(cfile.c_str());
  Model* model = doc->getModel();
  fail_unless(model != NULL);


  // SK - since I made the flattenModel package protected
  // this will no longer work
  // ===========
  //CompModelPlugin* cmp = static_cast<CompModelPlugin*>(model->getPlugin("comp"));
  //Model* flatmod = cmp->flattenModel();
  //fail_unless(flatmod != NULL);
  //SBMLNamespaces sbmlns(3,1,"comp",1);
  //SBMLDocument doc2(&sbmlns);
  //doc2.setPackageRequired("comp", true);
  //doc2.setModel(flatmod);
  //string newModel = writeSBMLToString(&doc2);
  //===========
  // replace with

  ConversionProperties* props = new ConversionProperties();
  
  props->addOption("flatten comp");
  props->addOption("leavePorts", true);

  SBMLConverter* converter = SBMLConverterRegistry::getInstance().getConverterFor(*props);
  converter->setDocument(doc);
  int result = converter->convert();

  // fail if conversion was not valid
  fail_unless(result == LIBSBML_OPERATION_SUCCESS);

  string newModel = writeSBMLToString(doc);

  string ffile = filename + "test14_A_flat_ports.xml";
  SBMLDocument* fdoc = readSBMLFromFile(ffile.c_str());
  string flatModel = writeSBMLToString(fdoc);
  fail_unless(flatModel == newModel);

  delete doc;
}
END_TEST


START_TEST(test_comp_flatten_abort_none_4)
{
  ConversionProperties* props = new ConversionProperties();
  
  props->addOption("flatten comp");
  
  // checking for none
  props->addOption("abortIfUnflattenable", "none");
  props->addOption("stripUnflattenablePackages", false);

  SBMLConverter* converter = 
    SBMLConverterRegistry::getInstance().getConverterFor(*props);
  
  // load document
  string dir(TestDataDirectory);
  string fileName = dir + "unknown1.xml";  
  SBMLDocument* doc = readSBMLFromFile(fileName.c_str());

  // fail if there is no model 
  //(but we have the unrecognised package error)
  fail_unless(doc->getNumErrors() == 1);
  fail_unless(doc->getModel() != NULL);
  fail_unless(doc->getErrorLog()->contains(UnrequiredPackagePresent) == true);

  converter->setDocument(doc);
  int result = converter->convert();

  fail_unless( result == LIBSBML_OPERATION_SUCCESS);

  string newModel = writeSBMLToString(doc);

  string ffile = dir + "unknown1_flat_stay.xml";
  SBMLDocument* fdoc = readSBMLFromFile(ffile.c_str());
  string flatModel = writeSBMLToString(fdoc);
  fail_unless(flatModel == newModel);

  delete doc;
  delete fdoc;
  delete converter;
}
SBMLDocument* TestFlattenedUnknownValidateNoStrip(string file1, string file2)
{
  string filename(TestDataDirectory);
  
  ConversionProperties props;
  
  props.addOption("flatten comp");
  props.addOption("basePath", filename);
  props.addOption("performValidation", true);
  props.addOption("stripUnflattenablePackages", false);
  props.addOption("abortIfUnflattenable", "none");

  SBMLConverter* converter = 
    SBMLConverterRegistry::getInstance().getConverterFor(props);
  
  // load document
  string cfile = filename + file1;  
  SBMLDocument* doc = readSBMLFromFile(cfile.c_str());

  // fail if there is no model (readSBMLFromFile always returns a valid document)
  fail_unless(doc->getModel() != NULL);

  converter->setDocument(doc);
  int result = converter->convert();

  // fail if conversion was not valid
  fail_unless(result == LIBSBML_OPERATION_SUCCESS);

  string newModel = writeSBMLToStdString(doc);

  string ffile = filename + file2;
  SBMLDocument* fdoc = readSBMLFromFile(ffile.c_str());
  string flatModel = writeSBMLToStdString(fdoc);
  
  fail_unless(flatModel == newModel);

  delete fdoc;
  delete converter;

  return doc;
}
END_TEST


START_TEST(test_comp_flatten_abort_all_3)
{
  ConversionProperties* props = new ConversionProperties();
  
  props->addOption("flatten comp");
  
  // checking the default
  props->addOption("abortIfUnflattenable", "all");
  props->addOption("stripUnflattenablePackages", false);

  SBMLConverter* converter = 
    SBMLConverterRegistry::getInstance().getConverterFor(*props);
  
  // load document
  string dir(TestDataDirectory);
  string fileName = dir + "unknown2.xml";  
  SBMLDocument* doc = readSBMLFromFile(fileName.c_str());

  // fail if there is no model 
  //(but we have the unrecognised package error)
  fail_unless(doc->getNumErrors() == 1);
  fail_unless(doc->getModel() != NULL);
  fail_unless(doc->getErrorLog()->contains(RequiredPackagePresent) == true);

  converter->setDocument(doc);
  int result = converter->convert();

  fail_unless( result == LIBSBML_OPERATION_FAILED);

  fail_unless(doc->getNumErrors() == 2);
  fail_unless(doc->getErrorLog()->contains(RequiredPackagePresent) == true);
  fail_unless(doc->getErrorLog()->contains(CompFlatteningNotRecognisedReqd) == true);

  delete doc;
  delete converter;
}
int main(int argc,char** argv)
{
  bool leavePorts = false;
  if (argc < 3)
  {
    cout << usage << endl;
    return 1;
  }
  else if (argc == 3)
  {
    if ( string("-p") == string(argv[1]) )
    {
      cout << usage << endl;
      return 1;
    }       
  }

  int  argIndex = 1;
  
  if ( string("-p") == string(argv[1]) )
  {
    leavePorts = true;
    ++argIndex;
  }     

  if (SBMLExtensionRegistry::isPackageEnabled("comp") == false)
  {
    cerr << "The version of libsbml being used does not have the comp"
      << " package code enabled" << endl;
    return 1;
  }

  const char* inputFile   = argv[argIndex];
  const char* outputFile  = argv[argIndex+1];

  SBMLDocument* document = readSBML(inputFile);

  if (document->getNumErrors() > 0)
  {
    cerr << "Encountered the following SBML errors:" << endl;
    document->printErrors(cerr);
    return 1;
  }

  ConversionProperties* props = new ConversionProperties();
  
  props->addOption("flatten comp");
  props->addOption("leavePorts", leavePorts);

  SBMLConverter* converter = 
             SBMLConverterRegistry::getInstance().getConverterFor(*props);
  

  converter->setDocument(document);
  
  int result = converter->convert();

  if (result != LIBSBML_OPERATION_SUCCESS)
  {
    cerr << "Conversion failed\n";
    document->printErrors();
  }

  writeSBML(document, outputFile);

}