bool CellmlFile::fullyInstantiateImports(iface::cellml_api::Model *pModel, CellmlFileIssues &pIssues) { // Fully instantiate all the imports, but only if we are dealing with a non // CellML 1.0 model, and then keep track of that fact (so we don't fully // instantiate everytime we come here) Version cellmlVersion = version(pModel); if ( mFullInstantiationNeeded && (cellmlVersion != Unknown) && (cellmlVersion != Cellml_1_0)) { try { // Note: the below is based on CDA_Model::fullyInstantiateImports(). // Indeed, CDA_Model::fullyInstantiateImports() doesn't work // with CellML imports that rely on https (see issue #417), so // rather than calling CDA_CellMLImport::instantiate(), we // call CDA_CellMLImport::instantiateFromText() instead, which // requires loading the imported CellML file. Otherwise, to // speed things up as much as possible, we cache the contents // of the URLs that we load... // Retrieve the list of imports, together with their XML base values ObjRef<iface::cellml_api::URI> baseUri = pModel->xmlBase(); QList<iface::cellml_api::CellMLImport *> importList = QList<iface::cellml_api::CellMLImport *>(); QStringList importXmlBaseList = QStringList(); retrieveImports(QString::fromStdWString(baseUri->asText()), pModel, importList, importXmlBaseList); // Instantiate all the imports in our list while (!importList.isEmpty()) { // Retrieve the first import and instantiate it, if needed ObjRef<iface::cellml_api::CellMLImport> import = importList.first(); QString importXmlBase = importXmlBaseList.first(); importList.removeFirst(); importXmlBaseList.removeFirst(); if (!import->wasInstantiated()) { // Note: CDA_CellMLImport::instantiate() would normally be // called, but it doesn't work with https, so we // retrieve the contents of the import ourselves and // instantiate it from text instead... ObjRef<iface::cellml_api::URI> xlinkHref = import->xlinkHref(); QString url = QUrl(importXmlBase).resolved(QString::fromStdWString(xlinkHref->asText())).toString(); bool isLocalFile; QString fileNameOrUrl; Core::checkFileNameOrUrl(url, isLocalFile, fileNameOrUrl); if (!fileNameOrUrl.compare(mFileName)) // We want to import ourselves, so... throw(std::exception()); else if (mImportContents.contains(fileNameOrUrl)) { // We have already loaded the import contents, so // directly instantiate the import with it import->instantiateFromText(mImportContents.value(fileNameOrUrl).toStdWString()); } else { // We haven't already loaded the import contents, so do // so now QString fileContents; if ( ( isLocalFile && Core::readTextFromFile(fileNameOrUrl, fileContents)) || (!isLocalFile && Core::readTextFromUrl(fileNameOrUrl, fileContents))) { // We were able to retrieve the import contents, so // instantiate the import with it import->instantiateFromText(fileContents.toStdWString()); // Keep track of the import contents mImportContents.insert(fileNameOrUrl, fileContents); } else { throw(std::exception()); } } // Now that the import is instantiated, add its own imports // to our list ObjRef<iface::cellml_api::Model> importModel = import->importedModel(); if (!importModel) throw(std::exception()); retrieveImports(isLocalFile? QUrl::fromLocalFile(fileNameOrUrl).toString(): fileNameOrUrl, importModel, importList, importXmlBaseList); } } mFullInstantiationNeeded = false; } catch (...) { // Something went wrong with the full instantiation of the imports pIssues << CellmlFileIssue(CellmlFileIssue::Error, QObject::tr("the imports could not be fully instantiated")); return false; } } return true; }