/* Copyright 2021 Equinor. This file is part of the Open Porous Media project (OPM). OPM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OPM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OPM. If not, see . */ #ifndef OPM_KEYWORDVALIDATION_HEADER_INCLUDED #define OPM_KEYWORDVALIDATION_HEADER_INCLUDED #include #include #include #include #include #include #include #include namespace Opm { class Deck; class DeckKeyword; class ErrorGuard; class ParseContext; namespace KeywordValidation { // Describe an unsupported keyword: struct UnsupportedKeywordProperties { bool critical; // Set to true if presence of the keyword should be an error std::optional message; // An optional message to show if the keyword is present }; // Describe a partially supported keyword item, by listing legal values: template struct PartiallySupportedKeywordProperties { bool critical; // Set to true if the unsupported item value should be an error std::function validator; // Predicate function to test values std::optional message; // An optional message to show if an illegal item is encountered }; // This is used to list unsupported kewyords. using UnsupportedKeywords = std::map; // This is used to list the partially supported items of a keyword: template using PartiallySupportedKeywordItems = std::map>; // This is used to list the keywords that have partially supported items: template using PartiallySupportedKeywords = std::map>; // This contains the information needed to report a single error occurence. // The validator will construct a vector of these, copying the relevant // information from the properties of the offending keywords and items. struct ValidationError { bool critical; // Determines if the encountered problem should be an error or a warning KeywordLocation location; // Location information (keyword name, file and line number) size_t record_number; // Number of the offending record std::optional item_number; // Number of the offending item std::optional item_value; // The offending value of a problematic item std::optional user_message; // An optional message to show if a problem is encountered }; // Get a formatted error report from a vector of validation errors. Set // critical to true if the report should contain only critical errors. If // critical is false, only non-critical errors are reported. If not // critical/non-critical errors are present, but the critical flag to reset // them, the result will be an empty string. std::string get_error_report(const std::vector& errors, const bool critical); // These are special case validation functions for keyword which do not fit nicely into the general // validation framework. The validation function itself is void, but error conditions are signalled by // appending ValidationError instances to the @errors vector. void validateBRINE(const DeckKeyword& keyword, std::vector& errors); class KeywordValidator { public: KeywordValidator(const UnsupportedKeywords& keywords, const PartiallySupportedKeywords& string_items, const PartiallySupportedKeywords& int_items, const PartiallySupportedKeywords& double_items, const std::unordered_map& errors)>>& special_validation) : m_keywords(keywords) , m_string_items(string_items) , m_int_items(int_items) , m_double_items(double_items) , m_special_validation(special_validation) { } // Validate a deck, reporting warnings and errors. If there are only // warnings, these will be reported. If there are errors, these are // reported, and execution of the program is halted. void validateDeck(const Deck& deck, const ParseContext& parse_context, ErrorGuard& error_guard) const; // Validate a single deck keyword. If a problem is encountered, add the // relevant information to the errors vector. void validateDeckKeyword(const DeckKeyword& keyword, std::vector& errors) const; private: template void validateKeywordItem(const DeckKeyword& keyword, const PartiallySupportedKeywordProperties& properties, const bool multiple_records, const size_t record_number, const size_t item_number, const T& item_value, std::vector& errors) const; template void validateKeywordItems(const DeckKeyword& keyword, const PartiallySupportedKeywords& partially_supported_options, std::vector& errors) const; const UnsupportedKeywords m_keywords; const PartiallySupportedKeywords m_string_items; const PartiallySupportedKeywords m_int_items; const PartiallySupportedKeywords m_double_items; const std::unordered_map& errors)>> m_special_validation; }; // Helper class to test if a given value is with a list of allowed values. template class allow_values { public: allow_values(const std::initializer_list& allowed_values) { for (auto item : allowed_values) { m_allowed_values.push_back(item); } } bool operator()(const T& value) const { return std::find(m_allowed_values.begin(), m_allowed_values.end(), value) != m_allowed_values.end(); } private: std::vector m_allowed_values; }; } // namespace KeywordValidation } // namespace Opm #endif