diff --git a/src/sbml/SBMLDocument.cpp b/src/sbml/SBMLDocument.cpp index 07d345c70..0d7aadf11 100644 --- a/src/sbml/SBMLDocument.cpp +++ b/src/sbml/SBMLDocument.cpp @@ -730,6 +730,12 @@ SBMLDocument::checkConsistency () } +unsigned int +SBMLDocument::checkConsistencyWithStrictUnits () +{ + return checkConsistencyWithStrictUnits(LIBSBML_OVERRIDE_ERROR); +} + /* * Performs a set of semantic consistency checks on the document. Query * the results by calling getNumErrors() and getError(). @@ -737,7 +743,7 @@ SBMLDocument::checkConsistency () * @return the number of failed checks (errors) encountered. */ unsigned int -SBMLDocument::checkConsistencyWithStrictUnits () +SBMLDocument::checkConsistencyWithStrictUnits (XMLErrorSeverityOverride_t strictErrorOverride /* = LIBSBML_OVERRIDE_ERROR */) { // keep a copy of the override status // and then override any change @@ -781,7 +787,7 @@ SBMLDocument::checkConsistencyWithStrictUnits () else { // log as errors - getErrorLog()->setSeverityOverride(LIBSBML_OVERRIDE_ERROR); + getErrorLog()->setSeverityOverride(strictErrorOverride); StrictUnitConsistencyValidator unit_validator; unit_validator.init(); unsigned int nerrors = unit_validator.validate(*this); diff --git a/src/sbml/SBMLDocument.h b/src/sbml/SBMLDocument.h index f94b74531..111581d28 100644 --- a/src/sbml/SBMLDocument.h +++ b/src/sbml/SBMLDocument.h @@ -305,7 +305,7 @@ #include #include #include - +#include #ifdef __cplusplus @@ -318,7 +318,6 @@ LIBSBML_CPP_NAMESPACE_BEGIN class Model; class ConversionProperties; class SBMLVisitor; -class XMLError; class SBMLValidator; class SBMLInternalValidator; @@ -341,7 +340,10 @@ class SBMLLevelVersionConverter; #define OverdeterCheckOFF 0xdf #define PracticeCheckON 0x40 #define PracticeCheckOFF 0xbf +#define StrictUnitsCheckON 0x80 +#define StrictUnitsCheckOFF 0x7f #define AllChecksON 0x7f +#define AllChecksONWithStrictUnits 0xff /** @endcond */ @@ -1005,12 +1007,36 @@ class LIBSBML_EXTERN SBMLDocument: public SBase * flag in the individual SBMLError objects returned by * SBMLDocument::getError(@if java long@endif) to determine the nature of the failures. * + * @param strictErrorOverride the severity of the error to use for strict units checking + * by default unit validations will be flagged as an error using this method. Use + * LIBSBML_OVERRIDE_WARNING to change this to a warning. + * * @return the number of failed checks (errors) encountered. * * @see SBMLDocument::checkInternalConsistency() */ unsigned int checkConsistencyWithStrictUnits (); + /** + * Performs consistency checking and validation on this SBML document + * using the ultra strict units validator that assumes that there + * are no hidden numerical conversion factors. + * + * If this method returns a nonzero value (meaning, one or more + * consistency checks have failed for SBML document), the failures may be + * due to warnings @em or errors. Callers should inspect the severity + * flag in the individual SBMLError objects returned by + * SBMLDocument::getError(@if java long@endif) to determine the nature of the failures. + * + * @param strictErrorOverride the severity of the error to use for strict units checking + * by default unit validations will be flagged as an error using this method. Use + * LIBSBML_OVERRIDE_WARNING to change this to a warning. + * + * @return the number of failed checks (errors) encountered. + * + * @see SBMLDocument::checkInternalConsistency() + */ + unsigned int checkConsistencyWithStrictUnits (XMLErrorSeverityOverride_t strictErrorOverride); /** * Performs consistency checking and validation on this SBML document. diff --git a/src/sbml/SBMLError.cpp b/src/sbml/SBMLError.cpp index ca03ae6c3..6903e8ddc 100644 --- a/src/sbml/SBMLError.cpp +++ b/src/sbml/SBMLError.cpp @@ -171,7 +171,8 @@ static struct sbmlCategoryString { { LIBSBML_CAT_MODELING_PRACTICE, "Modeling practice" }, { LIBSBML_CAT_INTERNAL_CONSISTENCY, "Internal consistency" }, { LIBSBML_CAT_SBML_L2V4_COMPAT, "Translation to SBML L2V4" }, - { LIBSBML_CAT_SBML_L3V1_COMPAT, "Translation to SBML L3V1Core" } + { LIBSBML_CAT_SBML_L3V1_COMPAT, "Translation to SBML L3V1Core" }, + { LIBSBML_CAT_STRICT_UNITS_CONSISTENCY, "Strict unit consistency" } }; static unsigned int sbmlCategoryStringTableSize diff --git a/src/sbml/SBMLError.h b/src/sbml/SBMLError.h index 3e59e1d37..3106785c2 100644 --- a/src/sbml/SBMLError.h +++ b/src/sbml/SBMLError.h @@ -1039,6 +1039,9 @@ typedef enum , LIBSBML_CAT_SBML_COMPATIBILITY /*!< Category of errors that can only occur during attempted * translation from one Level/Version of SBML to another. */ + , LIBSBML_CAT_STRICT_UNITS_CONSISTENCY + /*!< Category of errors that occur running the strict unit + * validator. */ } SBMLErrorCategory_t; diff --git a/src/sbml/test/TestConsistencyChecks.cpp b/src/sbml/test/TestConsistencyChecks.cpp index 26a8c24a7..55671d3b9 100644 --- a/src/sbml/test/TestConsistencyChecks.cpp +++ b/src/sbml/test/TestConsistencyChecks.cpp @@ -150,10 +150,55 @@ START_TEST (test_strict_unit_consistency_checks) fail_unless(d->getError(0)->getErrorId() == 10513); fail_unless(d->getError(0)->getSeverity() == LIBSBML_SEV_ERROR); + d->getErrorLog()->clearLog(); + + // now once more as warning + errors = d->checkConsistencyWithStrictUnits(LIBSBML_OVERRIDE_WARNING); + + fail_unless(errors == 1); + fail_unless(d->getError(0)->getErrorId() == 10513); + fail_unless(d->getError(0)->getSeverity() == LIBSBML_SEV_WARNING); + + + delete d; } END_TEST +START_TEST (test_check_consistency_settings) +{ + SBMLReader reader; + SBMLDocument* d; + unsigned int errors; + std::string filename(TestDataDirectory); + filename += "l3v1-units.xml"; + + + d = reader.readSBML(filename); + + if (d == NULL) + { + fail("readSBML(\"l3v1-units.xml\") returned a NULL pointer."); + } + + errors = d->checkConsistency(); + + fail_unless(errors == 0); + + d->getErrorLog()->clearLog(); + + // now enable the strict units check + d->setConsistencyChecks(LIBSBML_CAT_STRICT_UNITS_CONSISTENCY, true); + + errors = d->checkConsistency(); + + fail_unless(errors == 1); + fail_unless(d->getError(0)->getErrorId() == 10513); + fail_unless(d->getError(0)->getSeverity() == LIBSBML_SEV_WARNING); + + delete d; +} +END_TEST Suite * create_suite_TestConsistencyChecks (void) @@ -164,6 +209,7 @@ create_suite_TestConsistencyChecks (void) tcase_add_test(tcase, test_consistency_checks); tcase_add_test(tcase, test_strict_unit_consistency_checks); + tcase_add_test(tcase, test_check_consistency_settings); suite_add_tcase(suite, tcase); diff --git a/src/sbml/validator/SBMLInternalValidator.cpp b/src/sbml/validator/SBMLInternalValidator.cpp index b3aee0d39..e871ea27f 100644 --- a/src/sbml/validator/SBMLInternalValidator.cpp +++ b/src/sbml/validator/SBMLInternalValidator.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -176,6 +177,18 @@ SBMLInternalValidator::setConsistencyChecks(SBMLErrorCategory_t category, break; + case LIBSBML_CAT_STRICT_UNITS_CONSISTENCY: + if (apply) + { + mApplicableValidators |= StrictUnitsCheckON; + } + else + { + mApplicableValidators &= StrictUnitsCheckOFF; + } + + break; + case LIBSBML_CAT_OVERDETERMINED_MODEL: if (apply) { @@ -274,6 +287,18 @@ SBMLInternalValidator::setConsistencyChecksForConversion(SBMLErrorCategory_t cat break; + case LIBSBML_CAT_STRICT_UNITS_CONSISTENCY: + if (apply) + { + mApplicableValidatorsForConversion |= StrictUnitsCheckON; + } + else + { + mApplicableValidatorsForConversion &= StrictUnitsCheckOFF; + } + + break; + case LIBSBML_CAT_OVERDETERMINED_MODEL: if (apply) { @@ -329,6 +354,7 @@ SBMLInternalValidator::checkConsistency (bool writeDocument) bool units = ((mApplicableValidators & 0x10) == 0x10); bool over = ((mApplicableValidators & 0x20) == 0x20); bool practice = ((mApplicableValidators & 0x40) == 0x40); + bool strictUnits = ((mApplicableValidators & 0x80) == 0x80); /* taken the state machine concept out for now if (LibSBMLStateMachine::isActive()) @@ -505,6 +531,25 @@ SBMLInternalValidator::checkConsistency (bool writeDocument) } } + if (strictUnits) + { + StrictUnitConsistencyValidator unit_validator; + unit_validator.init(); + nerrors = unit_validator.validate(*doc); + total_errors += nerrors; + if (nerrors > 0) + { + log->add( unit_validator.getFailures() ); + /* only want to bail if errors not warnings */ + if (log->getNumFailsWithSeverity(LIBSBML_SEV_ERROR) > 0) + { + if (writeDocument) + SBMLDocument_free(doc); + return total_errors; + } + } + } + /* do not even try if there have been unit warnings * changed this as would have bailed */ if (over) diff --git a/src/sbml/validator/Validator.cpp b/src/sbml/validator/Validator.cpp index 8fbc809bc..6bfc230e3 100644 --- a/src/sbml/validator/Validator.cpp +++ b/src/sbml/validator/Validator.cpp @@ -864,7 +864,8 @@ Validator::validate (const SBMLDocument& d) if (m != NULL) { - if (this->getCategory() == LIBSBML_CAT_UNITS_CONSISTENCY) + if (this->getCategory() == LIBSBML_CAT_UNITS_CONSISTENCY || + this->getCategory() == LIBSBML_CAT_STRICT_UNITS_CONSISTENCY) { /* create list of formula units for validation */ if (!m->isPopulatedListFormulaUnitsData())