QStringList CellmlFileRuntime::componentHierarchy(iface::cellml_api::CellMLElement *pElement) { // Make sure that we have a given element if (!pElement) return QStringList(); // Try to retrieve the component that owns the given element, unless the // given element is a component itself (which will be the case when we come // here through recursion) ObjRef<iface::cellml_api::CellMLComponent> component = QueryInterface(pElement); ObjRef<iface::cellml_api::CellMLElement> parent = pElement->parentElement(); ObjRef<iface::cellml_api::CellMLComponent> parentComponent = QueryInterface(parent); if (!component && !parentComponent) { // The element isn't a component and neither is its parent, so it // doesn't have a hierarchy return QStringList(); } // Check whether this is an imported component and, if so, retrieve its // imported name QString componentName = QString::fromStdWString(component?component->name():parentComponent->name()); ObjRef<iface::cellml_api::CellMLElement> componentParent = component?component->parentElement():parentComponent->parentElement(); ObjRef<iface::cellml_api::CellMLElement> componentParentParent = componentParent->parentElement(); if (componentParentParent) { // The given element comes from or is an imported component, so go // through our different imported components and look for the one we are // after ObjRef<iface::cellml_api::CellMLImport> import = QueryInterface(componentParentParent); ObjRef<iface::cellml_api::ImportComponentSet> importComponents = import->components(); ObjRef<iface::cellml_api::ImportComponentIterator> importComponentsIter = importComponents->iterateImportComponents(); for (ObjRef<iface::cellml_api::ImportComponent> importComponent = importComponentsIter->nextImportComponent(); importComponent; importComponent = importComponentsIter->nextImportComponent()) { if (!componentName.compare(QString::fromStdWString(importComponent->componentRef()))) { // This is the imported component we are after, so retrieve its // imported name componentName = QString::fromStdWString(importComponent->name()); break; } } } // Recursively retrieve the component hierarchy of the given element's // encapsulation parent, if any ObjRef<iface::cellml_api::CellMLComponent> componentEncapsulationParent = component?component->encapsulationParent():parentComponent->encapsulationParent(); return componentHierarchy(componentEncapsulationParent) << componentName; }
bool CellmlFile::isValid() { if (!mValidNeeded) // The file has already been validated, so... return mValid; // Load (but not reload!) the file, if needed if (load()) { // The file was properly loaded (or was already loaded), so check // whether it is CellML valid // Note: validateModel() is somewhat slow, but there is (unfortunately) // nothing we can do about it. Then, there is getPositionInXML() // which is painfully slow, but unlike for validateModel() its use // is not essential (even though it would be nice from an // end-user's perspective). So, rather than retrieve the // line/column of every single warning/error, we only keep track // of the various warnings/errors and only retrieve their // corresponding line/column when requested (definitely not neat // from an end-user's perspective, but we just can't afford the // time it takes to fully validate a model that has many // warnings/errors)... ObjRef<iface::cellml_services::VACSService> vacssService = CreateVACSService(); ObjRef<iface::cellml_services::CellMLValidityErrorSet> cellmlValidityErrorSet = vacssService->validateModel(mModel); // Determine the number of errors and warnings // Note: CellMLValidityErrorSet::nValidityErrors() returns any type of // validation issue, be it an error or a warning, so we need to // determine the number of true errors int cellmlErrorsCount = 0; for (int i = 0, iMax = cellmlValidityErrorSet->nValidityErrors(); i < iMax; ++i) { ObjRef<iface::cellml_services::CellMLValidityError> cellmlValidityIssue = cellmlValidityErrorSet->getValidityError(i); ObjRef<iface::cellml_services::CellMLRepresentationValidityError> cellmlRepresentationValidityError = QueryInterface(cellmlValidityIssue); // Determine the issue's location uint32_t line = 0; uint32_t column = 0; QString importedFile = QString(); if (cellmlRepresentationValidityError) { // We are dealing with a CellML representation issue, so // determine its line and column ObjRef<iface::dom::Node> errorNode = cellmlRepresentationValidityError->errorNode(); line = vacssService->getPositionInXML(errorNode, cellmlRepresentationValidityError->errorNodalOffset(), &column); } else { // We are not dealing with a CellML representation issue, so // check whether we are dealing with a semantic one ObjRef<iface::cellml_services::CellMLSemanticValidityError> cellmlSemanticValidityError = QueryInterface(cellmlValidityIssue); if (cellmlSemanticValidityError) { // We are dealing with a CellML semantic issue, so determine // its line and column ObjRef<iface::cellml_api::CellMLElement> cellmlElement = cellmlSemanticValidityError->errorElement(); ObjRef<iface::cellml_api::CellMLDOMElement> cellmlDomElement = QueryInterface(cellmlElement); ObjRef<iface::dom::Element> domElement = cellmlDomElement->domElement(); line = vacssService->getPositionInXML(domElement, 0, &column); // Also determine its imported file, if any forever { // Retrieve the CellML element's parent ObjRef<iface::cellml_api::CellMLElement> cellmlElementParent = cellmlElement->parentElement(); if (!cellmlElementParent) break; // Check whether the parent is an imported file ObjRef<iface::cellml_api::Model> importedCellmlFile = QueryInterface(cellmlElementParent); if (!importedCellmlFile) break; // Retrieve the imported CellML element ObjRef<iface::cellml_api::CellMLElement> importedCellmlElement = importedCellmlFile->parentElement(); if (!importedCellmlElement) break; // Check whether the imported CellML element is an // import CellML element ObjRef<iface::cellml_api::CellMLImport> importCellmlElement = QueryInterface(importedCellmlElement); if (!importCellmlElement) break; ObjRef<iface::cellml_api::URI> xlinkHref = importCellmlElement->xlinkHref(); importedFile = QString::fromStdWString(xlinkHref->asText()); break; } } } // Determine the issue's type CellmlFileIssue::Type issueType; if (cellmlValidityIssue->isWarningOnly()) { // We are dealing with a warning issueType = CellmlFileIssue::Warning; } else { // We are dealing with an error ++cellmlErrorsCount; issueType = CellmlFileIssue::Error; } // Append the issue to our list mIssues << CellmlFileIssue(issueType, QString::fromStdWString(cellmlValidityIssue->description()), line, column, importedFile); } if (cellmlErrorsCount) // There are CellML errors, so... mValid = false; else // Everything went as expected, so... mValid = true; mValidNeeded = false; return mValid; } else { // Something went wrong with the loading of the file, so... return false;
bool CellmlFile::doIsValid(iface::cellml_api::Model *pModel, CellmlFileIssues &pIssues) { // Check whether the given model is CellML valid // Note: validateModel() is somewhat slow, but there is (unfortunately) // nothing we can do about it. Then, there is getPositionInXML() which // is painfully slow, but unlike for validateModel() its use is not // essential (even though it would be nice from an end-user's // perspective). So, rather than retrieve the line/column of every // single warning/error, we only keep track of the various // warnings/errors and only retrieve their corresponding line/column // when requested (definitely not neat from an end-user's perspective, // but we just can't afford the time it takes to fully validate a // model that has many warnings/errors)... // Make sure that pIssues is empty pIssues.clear(); // Determine the number of errors and warnings // Note: CellMLValidityErrorSet::nValidityErrors() returns any type of // validation issue, be it an error or a warning, so we need to // determine the number of true errors ObjRef<iface::cellml_services::VACSService> vacssService = CreateVACSService(); ObjRef<iface::cellml_services::CellMLValidityErrorSet> cellmlValidityErrorSet = vacssService->validateModel(pModel); int cellmlErrorsCount = 0; for (int i = 0, iMax = cellmlValidityErrorSet->nValidityErrors(); i < iMax; ++i) { ObjRef<iface::cellml_services::CellMLValidityError> cellmlValidityIssue = cellmlValidityErrorSet->getValidityError(i); ObjRef<iface::cellml_services::CellMLRepresentationValidityError> cellmlRepresentationValidityError = QueryInterface(cellmlValidityIssue); // Determine the issue's location uint32_t line = 0; uint32_t column = 0; QString importedFile = QString(); if (cellmlRepresentationValidityError) { // We are dealing with a CellML representation issue, so determine // its line and column ObjRef<iface::dom::Node> errorNode = cellmlRepresentationValidityError->errorNode(); line = vacssService->getPositionInXML(errorNode, cellmlRepresentationValidityError->errorNodalOffset(), &column); } else { // We are not dealing with a CellML representation issue, so check // whether we are dealing with a semantic one ObjRef<iface::cellml_services::CellMLSemanticValidityError> cellmlSemanticValidityError = QueryInterface(cellmlValidityIssue); if (cellmlSemanticValidityError) { // We are dealing with a CellML semantic issue, so determine its // line and column ObjRef<iface::cellml_api::CellMLElement> cellmlElement = cellmlSemanticValidityError->errorElement(); ObjRef<iface::cellml_api::CellMLDOMElement> cellmlDomElement = QueryInterface(cellmlElement); ObjRef<iface::dom::Element> domElement = cellmlDomElement->domElement(); line = vacssService->getPositionInXML(domElement, 0, &column); // Also determine its imported file, if any ObjRef<iface::cellml_api::CellMLElement> cellmlElementParent = cellmlElement->parentElement(); if (cellmlElementParent) { // Check whether the parent is an imported file ObjRef<iface::cellml_api::Model> importedCellmlFile = QueryInterface(cellmlElementParent); if (importedCellmlFile) { // Retrieve the imported CellML element ObjRef<iface::cellml_api::CellMLElement> importedCellmlElement = importedCellmlFile->parentElement(); if (importedCellmlElement) { // Check whether the imported CellML element is an // import CellML element ObjRef<iface::cellml_api::CellMLImport> importCellmlElement = QueryInterface(importedCellmlElement); if (importCellmlElement) { ObjRef<iface::cellml_api::URI> xlinkHref = importCellmlElement->xlinkHref(); importedFile = QString::fromStdWString(xlinkHref->asText()); } } } } } } // Determine the issue's type CellmlFileIssue::Type issueType; if (cellmlValidityIssue->isWarningOnly()) { // We are dealing with a warning issueType = CellmlFileIssue::Warning; } else { // We are dealing with an error ++cellmlErrorsCount; issueType = CellmlFileIssue::Error; } // Append the issue to our list pIssues << CellmlFileIssue(issueType, line, column, QString::fromStdWString(cellmlValidityIssue->description()), importedFile); } // Sort our issues std::sort(pIssues.begin(), pIssues.end()); return !cellmlErrorsCount; }