Example #1
0
bool Registry::LoadCellML(nsCOMPtr<cellml_apiIModel> model)
{
  if (model == NULL) return true;
  nsresult rv;
  nsString cellmltext;
  string cellmlname;
  nsCOMPtr<cellml_servicesICeVASBootstrap> cevasboot(do_GetService(CEVAS_BOOTSTRAP_CONTRACTID, &rv));
  NS_ENSURE_SUCCESS(rv, true);

  nsCOMPtr<cellml_servicesICeVAS> cevas;
  try {
    rv = cevasboot->CreateCeVASForModel(model, getter_AddRefs(cevas));
  }
  catch (...){
    return true;
  }
  if (NS_FAILED(rv)) {
    nsString error;
    cevas->GetModelError(error);
    SetError("Error reading CellML model:  " + ToThinString(error.get()));
    return true;
  }
  nsCOMPtr<cellml_apiICellMLComponentIterator> cmpi;
  rv = cevas->IterateRelevantComponents(getter_AddRefs(cmpi));
  nsCOMPtr<cellml_apiICellMLComponent> component;
  rv = cmpi->NextComponent(getter_AddRefs(component));
  int numcomps=0;
  vector<nsCOMPtr<cellml_apiICellMLComponent> > top_components;
  while (component != NULL) {
    numcomps++;
    //Each CellML 'component' becomes its own Antimony 'module'
    cellmlname = GetModuleNameFrom(component);
    FixName(cellmlname);
    Module* mod = GetModule(cellmlname);
    if (mod == NULL) {
      while (NewCurrentModule(&cellmlname)) {
        cellmlname += "_";
      }
      CurrentModule()->LoadCellMLComponent(component);
      RevertToPreviousModule();
    }
    else {
      //It's either a multiply-imported component, or a component with an identical name.
    }
    nsCOMPtr<cellml_apiICellMLComponent> parent;
    rv = component->GetEncapsulationParent(getter_AddRefs(parent));
    if (parent == NULL) {
      top_components.push_back(component);
    }
    rv = cmpi->NextComponent(getter_AddRefs(component));
  }
  if (numcomps == 0) {
    SetError("No components found in this CellML model.");
    return true;
  }

  //Now loop through all the components again, this time setting up 'encapsulation' for the submodules
  for (size_t topnum = 0; topnum<top_components.size(); topnum++) {
    component = top_components[topnum];
    rv = component->GetName(cellmltext);
    cellmlname = GetModuleNameFrom(component);
    Module* mod = GetModule(cellmlname);
    assert(mod != NULL);
    mod->SetCellMLChildrenAsSubmodules(component); // <- Here's where the work happens
  }

  //Now create a master model that contains only contain the top_components.
  rv = model->GetName(cellmltext);
  cellmlname = ToThinString(cellmltext.get());
  FixName(cellmlname);
  cellmlname += "__" MAINMODULE;
  while (NewCurrentModule(&cellmlname)) {
    //Failure - duplicated name
    cellmlname += "_";
  }
  CurrentModule()->LoadCellMLModel(model, top_components);

  //Now intercolate the connections into the modules.  First, get the connections from the imports:
  nsCOMPtr<cellml_apiICellMLImportSet> imports;
  rv = model->GetImports(getter_AddRefs(imports));
  nsCOMPtr<cellml_apiICellMLImportIterator> impi;
  rv = imports->IterateImports(getter_AddRefs(impi));
  nsCOMPtr<cellml_apiICellMLImport> import;
  rv = impi->NextImport(getter_AddRefs(import));
  while (import != NULL) {
    nsCOMPtr<cellml_apiIConnectionSet> impconnections;
    rv = import->GetImportedConnections(getter_AddRefs(impconnections));
    nsCOMPtr<cellml_apiIModel> impmodel;
    rv = import->GetImportedModel(getter_AddRefs(impmodel));
    LoadConnections(impconnections);
    rv = impi->NextImport(getter_AddRefs(import));
  }
  //And then get the main model's connections
  nsCOMPtr<cellml_apiIConnectionSet> connections;
  rv = model->GetConnections(getter_AddRefs(connections));
  LoadConnections(connections);

  CreateLocalVariablesForSubmodelInterfaceIfNeeded();
  //We've pulled a fast one here by inserting connections into models that were already copied into other models.  So, we need to go back through and pull those connections into the copied models.  We'll do this recursively by calling the routine on the top model.
  CurrentModule()->ReloadSubmodelVariables(CurrentModule()->GetModuleName());
  CurrentModule()->ReloadSubmodelConnections(CurrentModule());
  
  return false; //success
}