Retrieve Issue items

Selected libCellML classes contain a Logger whose job it is to curate any issues encountered within the class, and return them to the user when asked. The classes are:

  • the Parser class;

  • the Validator class;

  • the Printer class;

  • the Analyser class;

  • the Importer class; and

  • the Generator class.

Individual issues can be retrieved from the parent class by their index, an integer between 0 and issueCount()-1. Each issue contains a severity level indicator, one of four levels (ERROR, WARNING, HINT, or MESSAGE):

  • ERROR level indicates issues that must be resolved before the model is valid and runnable;

  • WARNING level indicates a non-fatal issue, but one that may cause hidden or unintended consequences;

  • HINT level indicates a commonly encountered valid-but-nonsense situation; and

  • MESSAGE level is for your information but does not require action.

Issues can also be retrieved from subgroups based on their severity, as shown in the examples below.

See C++ example

// Iterate through all the issues in a Validator, regardless of level, and print to the terminal.
for (size_t i = 0; i < validator->issueCount(); ++i) {
  // Retrieve the i-th issue and store it in the variable "myIssue".
  libcellml::IssuePtr myIssue = validator->issue(i);

  // Print the issue's description:
  std::cout << myIssue->description() << std::endl;

  // Print the issue's URL.  This is a URL at which more
  // information could be found about the cause and corrections
  // are needed to avoid it.
  std::cout << myIssue->url() << std::endl;

  // Validator only: Print the issue's reference. This is
  // the heading reference in the normative specification which
  // relates to this issue.
  std::cout << myIssue->referenceHeading() << std::endl;
}

// Retrieve the second ERROR level issue from a Printer. Note indexing from 0.
auto secondError = printer->error(1);

// Retrieve the last WARNING level issue from a Parser.
auto lastWarning = parser->warning(parser->warningCount()-1);

// Iterate through all HINT level issues in a Generator.
for (size_t h = 0; h < generator->hintCount(); ++h) {
  // Retrieve the h-th hint and store it in the variable "myHint".
  auto myHint = generator->hint(h);
}

See Python example

# Iterate through all the issues in a Validator, regardless of level, and print to the terminal.
for i in range(0, validator.issueCount()):
  # Retrieve the i-th issue and store it in the variable "my_issue".
  my_issue = validator.issue(i)

  # Print the issue's description:
  print(my_issue.description())

  # Print the issue's URL.  This is a URL at which more
  # information could be found about the cause and corrections
  # are needed to avoid it.
  print(my_issue.url())

  # Validator only: Print the issue's reference. This is
  # the heading reference in the normative specification which
  # relates to this issue.
  print(my_issue.referenceHeading())

# Retrieve the second ERROR level issue from a Printer. Note indexing from 0.
second_error = printer.error(1)

# Retrieve the last WARNING level issue from a Parser.
last_warning = parser.warning(parser.warningCount() - 1)

# Iterate through all HINT level issues in a Generator.
for h in range(0, generator.hintCount()):
  # Retrieve the h-th hint and store it in the variable "my_hint".
  my_hint = generator.hint(h)

Each Issue also contains the following attributes:

  • A description: a brief statement about the problem and how it might be fixed;

  • A reference heading: a chapter number pertaining to the formal CellML 2.0 Specification document, for issues related to formatting and specification;

  • A URL: a web address at which more detailed information and examples pertaining to the issue are available;

  • A cause: an enum which reports the type of item responsible for the issue. This is one of the enums:

  • COMPONENT,

  • CONNECTION,

  • ENCAPSULATION,

  • IMPORT,

  • MAP_VARIABLES,

  • MATHML,

  • MODEL,

  • RESET,

  • RESET_VALUE,

  • TEST_VALUE,

  • UNDEFINED,

  • UNIT,

  • UNITS,

  • VARIABLE, and

  • XML.

See C++ examples

// Retrieve and print the description of the issue.
std::cout << issue->description() << std::endl;

// Retrieve and print the reference heading number, if related to CellML2.0 specification and format.
std::cout << issue->referenceHeading() << std::endl;

// Retrieve and print the URL for more help and information about the issue.
std::cout << issue->url() << std::endl;

// Retrieve the item type - a libcellml::CellmlElementType enum - for the issue.
auto myType = issue->CellmlElementType();

// Retrieve the level - a libcellml::Issue::LEVEL enum - for the issue.
auto myLevel = issue->level();

See Python examples

# Retrieve and print the description of the issue.
print(issue.description())

# Retrieve and print the reference heading number, if related to CellML2.0 specification and format.
print(issue.referenceHeading())

# Retrieve and print the URL for more help and information about the issue.
print(issue.url())

# Retrieve the cause - a libcellml.CellmlElementType enum - for the issue.
my_type = issue.cellmlElementType()

# Retrieve the level - a libcellml.Issue.LEVEL enum - for the issue.
my_level = issue.level()

Useful functions for dealing with issues

Utility functions to retrieve issues

void printIssues(const libcellml::LoggerPtr &item) {

    // Get the number of issues attached to the logger item.  Note that this will 
    // return issues of all levels.  To retrieve the total number of a specific level
    // of issues, use the errorCount(), warningCount(), hintCount(), or messageCount() functions. 
    size_t num = item->issueCount();
    std::cout << "Recorded " << num << " issues";

    if (num != 0) {
        std::cout << ":" << std::endl;
        for (size_t i = 0; i < num; ++i) {

            // Retrieve the issue at index i.  Note that this is agnostic as to the level of issue.
            // Specific issue levels can be retrieved using the functions item->error(i), item->warning(i) 
            // etc, where the index must be within appropriate limits.
            libcellml::IssuePtr issue = item->issue(i);

            // Issues created by the Validator class contain a reference heading number, which indicates
            // the section reference within the normative specification relevant to the issue.
            std::string errorReference = issue->referenceHeading();

            // The level of an issue is retrieved using the level() function as an enum value.  
            std::cout << "Issue " << i << " is " << getIssueLevelFromEnum(issue->level()) << ":" << std::endl;

            // Each issue has a descriptive text field, accessible through the description() function.
            std::cout << "    description: " << issue->description() << std::endl;
            if (errorReference != "") {
                std::cout << "    see section " << errorReference
                          << " in the CellML specification." << std::endl;
            }

            // An optional URL is given for some issues which directs the user to more detailed information.
            if(!issue->url().empty()){
                std::cout << "    more information at: " <<issue->url() << std::endl;
            }

            // Each issue is associated with an item.  In order to properly deal with the item stored, its type is 
            // recorded too in an enumeration.
            std::cout << "    stored item type: " << getCellmlElementTypeFromEnum(issue->cellmlElementType()) << std::endl;
        }
        std::cout << std::endl << std::endl;
    }
    else {
        std::cout << "!" << std::endl << std::endl;
    }
}
std::map<libcellml::CellmlElementType, std::string> itemTypeToString = 
    {{libcellml::CellmlElementType::COMPONENT, "COMPONENT"},
    {libcellml::CellmlElementType::COMPONENT_REF, "COMPONENT_REF"},
    {libcellml::CellmlElementType::CONNECTION, "CONNECTION"},
    {libcellml::CellmlElementType::ENCAPSULATION, "ENCAPSULATION" },
    {libcellml::CellmlElementType::IMPORT, "IMPORT"},
    {libcellml::CellmlElementType::MAP_VARIABLES, "MAP_VARIABLES"},
    {libcellml::CellmlElementType::MATH, "MATH"},
    {libcellml::CellmlElementType::MODEL, "MODEL"},
    {libcellml::CellmlElementType::RESET, "RESET"},
    {libcellml::CellmlElementType::RESET_VALUE, "RESET_VALUE"},
    {libcellml::CellmlElementType::TEST_VALUE, "TEST_VALUE"},
    {libcellml::CellmlElementType::UNDEFINED, "UNDEFINED"},
    {libcellml::CellmlElementType::UNIT, "UNIT"},
    {libcellml::CellmlElementType::UNITS, "UNITS"}, 
    {libcellml::CellmlElementType::VARIABLE, "VARIABLE"}};

std::string getCellmlElementTypeFromEnum(libcellml::CellmlElementType t) {
    return itemTypeToString.at(t);
}
std::string getIssueLevelFromEnum(libcellml::Issue::Level myLevel)
{
    std::string myTypeAsString = "dunno";

    switch (myLevel) {
    case libcellml::Issue::Level::ERROR:
        myTypeAsString = "an ERROR";
        break;
    case libcellml::Issue::Level::WARNING:
        myTypeAsString = "a WARNING";
        break;
    case libcellml::Issue::Level::HINT:
        myTypeAsString = "a HINT";
        break;
    case libcellml::Issue::Level::MESSAGE:
        myTypeAsString = "a MESSAGE";
        break;
    }
    return myTypeAsString;
}

Full context: utilities.cpp